home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / ast.doc < prev    next >
Text File  |  1992-09-25  |  107KB  |  3,413 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.                                    Ast - A Generator for
  14.                                    Abstract Syntax Trees
  15.  
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                  Ast - A Generator for Abstract Syntax Trees
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                  Aug. 3, 1992
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                 Report No. 15
  93.  
  94.  
  95.                              Copyright c 1992 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                                      Ast                                     1
  135.  
  136.  
  137. 1.  Introduction
  138.  
  139.      Ast is a generator for program  modules  that  define  the  structure  of
  140. abstract  syntax  trees  and provide general tree manipulating procedures. The
  141. defined trees may be decorated with attributes  of  arbitrary  types.  Besides
  142. trees,  graphs can be handled, too. The structure of the trees is specified by
  143. a formalism based on context-free grammars.   The  generated  module  includes
  144. procedures  to  construct and destroy trees, to read and write trees from (to)
  145. files, and to traverse trees in some  commonly  used  manners.  The  mentioned
  146. readers and writers process ascii as well as binary tree representations.  All
  147. procedures work for graphs as well.
  148.  
  149.      The advantages of this approach are: record aggregates are provided which
  150. allow  a  concise notation for node creation. It is possible to build trees by
  151. writing terms. An extension mechanism avoids chain rules and allows, for exam-
  152. ple  lists  with  elements  of  different  types.  Input/output procedures for
  153. records and complete graphs  are  provided.  The  output  procedures  and  the
  154. interactive  graph browser facilitate the debugging phase as they operate on a
  155. readable level and know the data structure.  The user does not  have  to  care
  156. about algorithms for traversing graphs. He/she is freed from the task of writ-
  157. ing large amounts of relatively simple code.  All of these  features  signifi-
  158. cantly increase programmer productivity.
  159.  
  160.      Ast is implemented in Modula-2 as well as in C and generates Modula-2  or
  161. C  source  modules.  The following sections define the specification language,
  162. explain the generated output, discuss related  approaches,  and  present  some
  163. examples.
  164.  
  165. 2.  Specification
  166.  
  167.      The structure of trees and directed graphs is specified  by  a  formalism
  168. based  on context-free grammars.  However, we primarily use the terminology of
  169. trees and types in defining the specification language.  Its  relationship  to
  170. context-free grammars is discussed later.
  171.  
  172. 2.1.  Node Types
  173.  
  174.      A tree consists of nodes.  A node may be related to other nodes in a  so-
  175. called  parent-child relation. Then the first node is called a parent node and
  176. the latter nodes are called child nodes. Nodes without a parent node are  usu-
  177. ally called root nodes, nodes without children are called leaf nodes.
  178.  
  179.      The structure and the properties of nodes are described  by  node  types.
  180. Every  node  belongs  to  a node type.  A specification for a tree describes a
  181. finite number of node types.  A node type specifies the  names  of  the  child
  182. nodes and the associated node types as well as the names of the attributes and
  183. the associated attribute types.  A node type is introduced by a name which can
  184. be an identifier or a string.  The names of all node types have to be pairwise
  185. distinct.  A node type can be regarded as a nonterminal,  a  terminal,  or  an
  186. abstract entity. Nonterminals are characterized by the character '=' following
  187. its name, terminals by the character ':', and abstract node types by the char-
  188. acters  ':='.   Undefined  node  types  are implicitly defined to be terminals
  189. without attributes. The distinction between nonterminals and terminals is only
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                      Ast                                     2
  201.  
  202.  
  203. of  interest  if  concrete syntax is described. In the case of abstract syntax
  204. this distinction does not make sense and therefore nonterminal node types  and
  205. eventually  abstract  ones suffice.  Abstract node types are explained in sec-
  206. tion 2.6.
  207.  
  208.     Example:
  209.        If        = .
  210.        While     = .
  211.        '()'      = .
  212.        Ident     : .
  213.        ":="      : .
  214.        SCOPE     := .
  215.  
  216. The example defines the node types If, While, and '()' to be nonterminals, the
  217. node  types  Ident  and ":=" to be terminals, and SCOPE to be an abstract node
  218. type.
  219.  
  220.      The following names are reserved for keywords and can  not  be  used  for
  221. node types:
  222.  
  223.     BEGIN           CLOSE           DECLARE         DEMAND          END
  224.     EVAL            EXPORT          FOR             FUNCTION        GLOBAL
  225.     IGNORE          IMPORT          IN              INH             INHERITED
  226.     INPUT           LEFT            LOCAL           MODULE          NONE
  227.     OUT             OUTPUT          PARSER          PREC            PROPERTY
  228.     REMOTE          REV             REVERSE         RIGHT           RULE
  229.     SCANNER         SELECT          STACK           SUBUNIT         SYN
  230.     SYNTHESIZED     THREAD          TREE            VIEW            VIRTUAL
  231.     VOID
  232.  
  233.  
  234. 2.2.  Children
  235.  
  236.      Children are distinguished by selector names which have to be unambiguous
  237. within one node type.  The children are of a certain node type.
  238.  
  239.     Example:
  240.        If        = Expr: Expr Then: Stats Else: Stats .
  241.        While     = Expr: Expr Stats: Stats .
  242.  
  243. The example introduces two node types called If and While.  A node of type  If
  244. has  three children which are selected by the names Expr, Then, and Else.  The
  245. children have the node types Expr, Stats, and Stats.
  246.  
  247.      If a selector name is equal to the associated name of the  node  type  it
  248. can be omitted. Therefore, the above example can be abbreviated as follows:
  249.  
  250.        If        = Expr Then: Stats Else: Stats .
  251.        While     = Expr Stats .
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.                                      Ast                                     3
  265.  
  266.  
  267. 2.3.  Attributes
  268.  
  269.      As well as children, every node type can specify an arbitrary  number  of
  270. attributes  of arbitrary types. Like children, attributes are characterized by
  271. a selector name and a  certain  type.   The  descriptions  of  attributes  are
  272. enclosed  in  brackets.  The attribute types are given by names taken from the
  273. target language. Missing attribute types are assumed  to  be  int  or  INTEGER
  274. depending on the target language (C or Modula-2).  Children and attributes can
  275. be given in any order.  The type of an attribute can be a pointer  to  a  node
  276. type.  In contrast to children, ast does not follow such an attribute during a
  277. graph traversal. All attributes are considered to be neither  tree  nor  graph
  278. structured.  Only  the  user knows about this fact and therefore he/she should
  279. take care.
  280.  
  281.     Example:
  282.        Binary        = Lop: Expr Rop: Expr [Operator: int] .
  283.        Unary         = Expr [Operator] .
  284.        IntConst      = [Value] .
  285.        RealConst     = [Value: float] .
  286.  
  287.  
  288.      For example the node types IntConst and  RealConst  describe  leaf  nodes
  289. with  an attribute named Value of types int or float respectively.  Binary and
  290. Unary are node types with an attribute called Operator of type int.
  291.  
  292. 2.4.  Declare Clause
  293.  
  294.      The DECLARE clause allows the definition of children and  attributes  for
  295. several  node  types  at  one  time.   Following the keyword DECLARE, a set of
  296. declarations can be given. The syntax is the same as described above with  the
  297. exception  that several node type names may introduce a declaration.  If there
  298. already exists a declaration for a  specified  node  type,  the  children  and
  299. attributes are added to this declaration.  Otherwise a new node type is intro-
  300. duced.
  301.  
  302.     Example:
  303.     DECLARE
  304.        Decls Stats Expr = -> [Level] [Env: tEnv] .
  305.                    Expr = -> Code [Type: tType] .
  306.  
  307.  
  308. 2.5.  Extensions
  309.  
  310.      To allow several alternatives for the  types  of  children  an  extension
  311. mechanism is used. A node type may be associated with several other node types
  312. enclosed in angle brackets. The first node type is called base or  super  type
  313. and the latter types are called derived types or subtypes.  A derived type can
  314. in turn be extended with no limitation of the nesting  depth.   The  extension
  315. mechanism  induces  a  subtype  relation between node types.  This relation is
  316. transitive.  Where a node of a certain node type is required, either a node of
  317. this node type or a node of a subtype thereof is possible.
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.                                      Ast                                     4
  329.  
  330.  
  331.     Example:
  332.     Stats           = <
  333.        If           = Expr Then: Stats Else: Stats .
  334.        While        = Expr Stats .
  335.     > .
  336.  
  337.  
  338.      In the above example Stats is a base type describing nodes  with  neither
  339. children nor attributes.  It has two derived types called If and While.  Where
  340. a node of type Stats is required, nodes of types Stats, If, and While are pos-
  341. sible.   Where  a  node of type If is required, nodes of type If are possible,
  342. only.
  343.  
  344.      Besides extending the set of possible node types, the extension mechanism
  345. has  the property of extending the children and attributes of the nodes of the
  346. base type.  The derived types possess the children and attributes of the  base
  347. type.   They  may  define  additional children and attributes.  In other words
  348. they inherit the structure of the base type.  The selector names of all  chil-
  349. dren  and attributes in an extension hierarchy have to be distinct. The syntax
  350. of extensions has been designed this way in order to allow single inheritance,
  351. only. Multiple inheritance is available, too. It is described in the next sec-
  352. tion.
  353.  
  354.     Example:
  355.     Stats           = Next: Stats [Pos: tPosition] <
  356.        If           = Expr Then: Stats Else: Stats .
  357.        While        = Expr Stats .
  358.     > .
  359.  
  360.  
  361.      Nodes of type Stats have one child selected by  the  name  Next  and  one
  362. attribute  named Pos.  Nodes of type While have three children with the selec-
  363. tor names Next, Expr, and Stats and one attribute named Pos.
  364.  
  365.      A node of a base type like Stats usually does not occur  in  an  abstract
  366. syntax  tree  for  a  complete program.  Still, ast defines this node type. It
  367. could be used as placeholder for unexpanded nonterminals  in  incomplete  pro-
  368. grams which occur in applications like syntax directed editors.
  369.  
  370. 2.6.  Multiple Inheritance
  371.  
  372.      The extension mechanism described in the previous section allows for sin-
  373. gle  inheritance  of children and attributes. The syntax of the extensions has
  374. been designed to reflect the notation of context-free  grammars  as  close  as
  375. possible.  For  multiple  inheritance  a  different  syntax and the concept of
  376. abstract node types are used.
  377.  
  378.      Abstract node types are characterized by the definition  characters  ':='
  379. instead  of  '=' or ':' which are used for nonterminals or terminals. They are
  380. termed abstract because they describe only the structure  of  nodes  or  parts
  381. thereof  but nodes of this types do not exist.  Therefore no code is generated
  382. by for abstract node types:  no  constant,  no  record  type,  no  constructor
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.                                      Ast                                     5
  394.  
  395.  
  396. procedure, etc..  Abstract node types can be used as base types in combination
  397. with multiple inheritance.
  398.  
  399.      For multiple inheritance the following syntax is used: The name of a node
  400. type  may be followed by a left arrow '<-' and a list of names. This construct
  401. is available for all three kinds of node types: nonterminals,  terminals,  and
  402. abstract  node  types.  The names after the left arrow have to denote abstract
  403. node types. The meaning is that the node type inherits the  structure  of  all
  404. listed  abstract  node  types.  Multiple inheritance is possible from abstract
  405. node types to non abstract ones and  among  abstract  node  types.  Among  non
  406. abstract node types only single inheritance is allowed.
  407.  
  408.     Example:
  409.     DECLS              := [Objects: tObjects THREAD] <
  410.       NODECLS          := .
  411.       DECL             := [Ident: tIdent INPUT] Next:DECLS .
  412.     > .
  413.     ENV                := [Env: tEnv INH] .
  414.     USE   <- ENV       := [Ident: tIdent INPUT] [Object: tObject SYN] .
  415.     SCOPE <- ENV       := [Objects: tObjects SYN] [NewEnv: tEnv SYN] .
  416.  
  417.  
  418.     Root               = Proc .
  419.     Decls <- DECLS ENV = <
  420.       NoDecls          = .
  421.       Decl <- DECL     = <
  422.         Var            = .
  423.         Proc <- SCOPE  = Decls Stats .
  424.       > .
  425.     > .
  426.     Stats <- ENV       = <
  427.       NoStats          = .
  428.       Stat             = <
  429.         Assign         = Name Expr .
  430.         Call <- USE    = .
  431.       > .
  432.     > .
  433.     Expr <- ENV        = <
  434.       Plus             = Lop: Expr Rop: Expr .
  435.       Const            = [Value] .
  436.       Name <- USE      = .
  437.     > .
  438.  
  439.  
  440.      The above example uses multiple inheritance and abstract  node  types  to
  441. describe  the  identification problem of programming languages. The node types
  442. written with all upper-case  letters  represent  abstract  node  types.  DECLS
  443. specifies  lists  of  declared  objects,  SCOPE describes scopes or visibility
  444. regions, ENV stands for environment and is used to distribute  scope  informa-
  445. tion, and USE is intended to be used at the application of identifiers. In the
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.                                      Ast                                     6
  457.  
  458.  
  459. second part of the example, the abstract node types are connected to nontermi-
  460. nal node types.  Decls is the concrete node type to describe lists of declara-
  461. tions.  Decl represents one declaration and there are to alternatives, Var and
  462. Proc,  variables  and procedures. A procedure introduces a scope and therefore
  463. it inherits from SCOPE.  At the node types Call and Name identifiers are  used
  464. and thus they inherit from USE. Finally, the node types Decls, Stats, and Expr
  465. are regions where the environment information has to be distributed  and  they
  466. inherit from ENV.
  467.  
  468. 2.7.  Modules
  469.  
  470.      The specification of node types can be grouped into an  arbitrary  number
  471. of modules.  The modules allow to combine parts of the specification that log-
  472. ically belong together.  This feature can be used to structure a specification
  473. or  to extend an existing one.  A module consists of target code sections (see
  474. section 2.12.) and specifications of node types with  attribute  declarations.
  475. The  information given in the modules is merged in the following way: the tar-
  476. get code sections are concatenated.  If a node type has already been  declared
  477. the  given  children,  attributes,  and  subtypes  are  added  to the existing
  478. declaration.  Otherwise a new node type is introduced.  This way of  modulari-
  479. zation offers several possibilities:
  480.  
  481. -    Context-free grammar and attribute declarations (=  node  types)  can  be
  482.      combined in one module.
  483.  
  484. -    The context-free grammar and the attribute declarations can be placed  in
  485.      two separate modules.
  486.  
  487. -    The attribute declarations can be subdivided into several modules accord-
  488.      ing  to  the  tasks  of  semantic  analysis.  For example, there would be
  489.      modules for scope handling, type determination, and context conditions.
  490.  
  491. -    The information can be grouped according to language concepts or  nonter-
  492.      minals.  For example, there would be modules containing the grammar rules
  493.      and the attribute declarations for declarations, statements, and  expres-
  494.      sions.
  495.  
  496.     Example:
  497.     MODULE my_version
  498.     Stats        = [Env: tEnv] <                    /* add attribute   */
  499.        While     = Init: Stats Terminate: Stats .   /* add children    */
  500.        Repeat    = Stats Expr .                     /* add node type   */
  501.     > .
  502.     END my_version
  503.  
  504.  
  505. 2.8.  Properties
  506.  
  507.      The description of children and attributes can be refined by the associa-
  508. tion  of  so-called properties. These properties are expressed by the keywords
  509. listed in Table 1.
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.                                      Ast                                     7
  521.  
  522.  
  523.  
  524.                Table 1: Properties for Children and Attributes
  525.  
  526.                            long form     short form
  527.                            ________________________
  528.                            INPUT         IN
  529.                            OUTPUT        OUT
  530.                            SYNTHESIZED   SYN
  531.                            INHERITED     INH
  532.                            THREAD
  533.                            REVERSE       REV
  534.                            IGNORE
  535.                            VIRTUAL
  536.  
  537.  
  538.      The properties have the following meanings: Input  attributes  (or  chil-
  539. dren)  receive a value at node-creation time, whereas non-input attributes may
  540. receive their values at later times.  Output attributes are supposed to hold a
  541. value  at  the  end  of  a node's existence, whereas non-output attributes may
  542. become undefined or unnecessary earlier.  Synthesized and  inherited  describe
  543. the  kinds of attributes occurring in attribute grammars. They have no meaning
  544. for ast.  The property  thread  supports  so-called  threaded  attributes:  An
  545. attribute declaration [a THREAD] is equivalent to the declaration of a pair of
  546. attributes with the suffixes In and Out: [aIn] [aOut].  These attributes  have
  547. to  be  accessed  with  their  full name including the suffixes.  The property
  548. reverse specifies how lists should be reversed. It  is  discussed  in  section
  549. 2.11.   The property ignore instructs ast to disregard or omit an attribute or
  550. a child. It is useful in connection with the concept  of  views  (see  section
  551. 2.10.).   The property virtual is meaningful in attribute grammars. It is used
  552. to describe dependencies among attributes.  However, no space  will  be  allo-
  553. cated for those attributes and the attribute computations for those attributes
  554. will be omitted in the generated attribute evaluator.  Within ast the  proper-
  555. ties input, reverse, and ignore are of interest, only.
  556.  
  557.      Properties are specified either locally or globally. Local properties are
  558. valid for one individual child or attribute. They are listed after the type of
  559. this item. Example:
  560.  
  561.     Stats = Next: Stats IN REV [Pos: tPosition IN] [Level INH] .
  562.  
  563. Global properties are valid for all children and attributes defined in one  or
  564. several modules. They are valid in addition to the local properties that might
  565. be specified. In order to describe global properties,  a  module  may  contain
  566. several property clauses which are written in the following form:
  567.  
  568.     PROPERTY properties [ FOR module_names ]
  569.  
  570. The listed properties become valid for the given modules. If the FOR  part  is
  571. missing, the properties become valid for the module that contains the clause.
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.                                      Ast                                     8
  586.  
  587.  
  588.     Example:
  589.     PROPERTY INPUT
  590.     PROPERTY SYN OUT FOR Mapping
  591.  
  592.  
  593.      Input attributes are included into the parameter list of  the  node  con-
  594. structor  procedures  (see  section 3). The global property input replaces the
  595. symbol '->' of former versions of ast.  For compatibility reasons this  symbol
  596. still  works  in a restricted way: The symbol '->' could be included in a list
  597. of children and attributes as a shorthand  notation  to  separate  input  from
  598. non-input items. In a list without this symbol all children and attributes are
  599. treated as input items.  This meaning of the symbol '->' is still in effect as
  600. long  as  ast  does not encounter a global property clause. After encountering
  601. such a clause, local and global properties are in effect only  the symbol '->'
  602. is ignored.
  603.  
  604.     Example:
  605.     Stats           = Next: Stats REV [Pos: tPosition] -> [Level INH] <
  606.        If           = Expr Then: Stats Else: Stats .
  607.        While        = -> Expr IN Stats IN .
  608.     > .
  609.  
  610. The node types of the example possess the children and  attributes  listed  in
  611. Table 2.
  612.  
  613.  
  614.  
  615.  
  616.  
  617.                         Table 2: Example of Properties
  618.  
  619.             node    selector   associated   kind        properties
  620.             type    name       type
  621.             ______________________________________________________
  622.             Stats   Next       Stats        child       IN REV
  623.                     Pos        tPosition    attribute   IN
  624.                     Level      int          attribute   INH
  625.             ______________________________________________________
  626.             If      Next       Stats        child       IN REV
  627.                     Pos        tPosition    attribute   IN
  628.                     Level      int          attribute   INH
  629.                     Expr       Expr         child       IN
  630.                     Then       Stats        child       IN
  631.                     Else       Stats        child       IN
  632.             ______________________________________________________
  633.             While   Next       Stats        child       IN REV
  634.                     Pos        tPosition    attribute   IN
  635.                     Level      int          attribute   INH
  636.                     Expr       Expr         child       IN
  637.                     Stats      Stats        child       IN
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.                                      Ast                                     9
  652.  
  653.  
  654. 2.9.  Subunits
  655.  
  656.      Usually, an ast specification is translated into one program module. This
  657. module  receives  the  name  that  immediately  follows  the keyword TREE.  If
  658. several modules contain a name, the first one  is  chosen.   If  none  of  the
  659. modules contains a name, the default name Tree is used. It is possible to gen-
  660. erate several modules out of an ast specification. Then there is  exactly  one
  661. module  called  main  unit  that describes the tree structure and an arbitrary
  662. number of modules called subunits.  This  is  of  interest  if  the  generated
  663. source  code  becomes too large for one compilation unit.  Then either some or
  664. all desired procedures could be placed into separate subunits. In the extreme,
  665. there  might  be  a subunit for every procedure. It is possible to have two or
  666. more versions of one procedure (e. g. WriteTREE) where every one uses  a  dif-
  667. ferent view (see section 2.10.).
  668.  
  669.      The names of the main unit and the subunits are described in  the  header
  670. of an ast specification:
  671.  
  672.     [ TREE [ Name ] ] [ SUBUNIT Name ] [ VIEW Name ]
  673.  
  674. The name after the keyword VIEW is necessary if abstract syntax trees  are  to
  675. be processed by program modules generated with other tools such as e. g.  puma
  676. [Gro91] that need to know the definition of the tree structure.   Ast  has  an
  677. option  that  requests  to  write a binary version of the tree definition to a
  678. file whose name is derived from the name  given  after  the  keyword  VIEW  by
  679. appending the suffix ".TS" (Default: "Tree.TS").
  680.  
  681.      Every unit has to be generated by a separate run of ast.   If  a  subunit
  682. name  is  present,  then a subunit is generated  otherwise a main unit is gen-
  683. erated. The options select the procedures to be included in the units.  It  is
  684. probably wise not to include the subunit name in an ast specification. If this
  685. name is added "on the fly" with UNIX commands then different subunits  can  be
  686. generated from one specification without the need to change it.
  687.  
  688.     Example:
  689.                                           ast -dim spec.ast
  690.     echo SUBUNIT read  | cat - spec.ast | ast -dir
  691.     echo SUBUNIT write | cat - spec.ast | ast -diw
  692.     or
  693.     echo TREE MyTree               | cat - spec.ast | ast -dim
  694.     echo TREE MyTree SUBUNIT read  | cat - spec.ast | ast -dir
  695.     echo TREE MyTree SUBUNIT write | cat - spec.ast | ast -diw
  696.  
  697.  
  698. 2.10.  Views
  699.  
  700.      An ast specification can be roughly seen as a collection  of  node  types
  701. and  associated  children and attributes. A so-called view selects a subset of
  702. this collection and it may attach further properties to  some  parts  of  this
  703. collection.
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.                                      Ast                                    10
  717.  
  718.  
  719.      The concept of views is necessary for instance if two  programs  communi-
  720. cate  a  common data structure via a file. Every program might need additional
  721. data which should neither appear in the other program  nor  in  the  file.  In
  722. order  to  make this work both programs must agree upon the coding of the node
  723. types in the shared part of the data structure. This is accomplished by  using
  724. one  common  ast  specification  that contains the description of the complete
  725. data structure. Every program uses a specific  view  and  selects  only  those
  726. parts  of  the  common specification that are of interest. See Figure 1 for an
  727. example.
  728.  
  729.      Another need for views arises if several attribute evaluators operate one
  730. after  the  other  on one tree. The output attributes of a preceding evaluator
  731. become the input attributes of a succeeding one. Here it is  necessary  to  be
  732. able  to  change  the properties of attributes. In one view the attributes are
  733. regarded as output and in the other one they are regarded as input. The  usage
  734. of views for the specification of several attribute evaluators is described in
  735. [Gro89].
  736.  
  737.      Furthermore, views are necessary if abstract syntax trees are to be  pro-
  738. cessed  by  program  modules  generated  with  other tools such as e. g.  puma
  739. [Gro91] that need to know the definition of the tree structure.   In  general,
  740. there  might be several tree processing modules and every one uses a different
  741. view. In this case, the views have to be communicated to the other tool  in  a
  742. file.   ast  has an option that requests to write a binary version of the tree
  743. definition to a file whose name is derived from the name given after the  key-
  744. word  VIEW  by  appending the suffix ".TS" (Default: "Tree.TS", see section on
  745. "Subunits").
  746.  
  747.      The concept of views is based on the global properties:
  748.  
  749.     PROPERTY properties FOR module_names
  750.  
  751. allows the dynamic addition of properties.
  752.  
  753.     PROPERTY IGNORE FOR module_names
  754.  
  755. allows the suppression of all definitions given in the listed  modules.  Addi-
  756. tionally there is the so-called select clause:
  757.  
  758.     SELECT module_names
  759.  
  760. This is equivalent to:
  761.  
  762.  
  763.                UNIX commands to generate the compilation units:
  764.          echo                 SELECT A C | cat - spec.ast | ast -dim
  765.          echo SUBUNIT PutTree SELECT   C | cat - spec.ast | ast -dip
  766.          echo                 SELECT B C | cat - spec.ast | ast -dim
  767.          echo SUBUNIT GetTree SELECT   C | cat - spec.ast | ast -dig
  768.  
  769.              Fig. 1: Programs Sharing a Part of a Data Structure
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.                                      Ast                                    11
  782.  
  783.  
  784.     PROPERTY IGNORE FOR module_names_not_given
  785.  
  786.  
  787.      It is wise to assign names  to  all  modules  of  an  ast  specification,
  788. because  otherwise  they can not be selected with the select clause.  Further-
  789. more, the property or select clauses that express views should probably not be
  790. included in the file containing the ast specification. The reason is that this
  791. form is not flexible, because it is relatively hard to change. It is better to
  792. add  the one line that is necessary for views "on the fly" using UNIX commands
  793. like echo and cat (see Figure 1).
  794.  
  795. 2.11.  Reversal of Lists
  796.  
  797.      Recursive node types like Stats in the abstract grammar  of  the  example
  798. below  describe  lists  of subtrees.  There are at least two cases where it is
  799. convenient to be able to easily reverse the order of the subtrees in  a  list.
  800. The  facility  provided  by  ast  is  a generalization of an idea presented in
  801. [Par88].
  802.  
  803. 2.11.1.  LR Parsers
  804.  
  805.      Using LR parsers, one might be forced to  parse  a  list  using  a  left-
  806. recursive  concrete  grammar rule because of the limited stack size.  The con-
  807. crete grammar rules of  the  following  examples  are  written  in  the  input
  808. language  of  the  parser generator Lalr [GrV88,Gro88] which is similar to the
  809. one of YACC [Joh75].  The node  constructor  procedures  within  the  semantic
  810. actions are the ones provided by ast (see section 3).
  811.  
  812.     Example:
  813.     concrete grammar (with tree building actions):
  814.     Stats:                         {$$ = mStats0 ();      } .
  815.     Stats: Stats Stat ';'          {$$ = mStats1 ($2, $1);} .
  816.     Stat : WHILE Expr DO Stats END {$$ = mWhile  ($2, $4);} .
  817.     abstract grammar:
  818.     Stats           = <
  819.        Stats0       = .
  820.        Stats1       = Stat Stats .
  821.     > .
  822.  
  823. A parser using the above concrete  grammar  would  construct  statement  lists
  824. where  the list elements are in the wrong order, because the last statement in
  825. the source would be the first one in the list. The  WHILE  rule  represents  a
  826. location where statement lists are used.
  827.  
  828.      To easily solve this problem ast can  generate  a  procedure  to  reverse
  829. lists.   The  specification  has to describe how this should be done.  At most
  830. one child of every node type may be given the property reverse.   The  child's
  831. type has to be the node type itself or an associated base type.  The generated
  832. list reversal procedure ReverseTREE then reverses a list with respect to  this
  833. indicated  child.  The procedure ReverseTREE has to be called exactly once for
  834. a list to be reversed. This is the case at the location where a complete  list
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.                                      Ast                                    12
  846.  
  847.  
  848. is included as subtree (e. g. in a WHILE statement).
  849.  
  850.     Example:
  851.     concrete grammar (with tree building actions):
  852.     Stats:                         {$$ = mStats0 ();      } .
  853.     Stats: Stats Stat ';'          {$$ = mStats1 ($2, $1);} .
  854.     Stat : WHILE Expr DO Stats END {$$ = mWhile  ($2, ReverseTREE ($4));} .
  855.     abstract grammar:
  856.     Stats           = <
  857.        Stats0       = .
  858.        Stats1       = Stat Stats REVERSE .
  859.     > .
  860.  
  861.  
  862.      It is possible to represent lists differently in an abstract  syntax.   A
  863. more  sophisticated  solution  is  given  in  the next example.  The procedure
  864. ReverseTREE handles this variant, too.
  865.  
  866.     Example:
  867.     concrete grammar (with tree building actions):
  868.     Stats:       {$$ = mEmpty ();} .
  869.     Stats: Stats IF Expr THEN Stats ELSE Stats END ';'
  870.                  {$$ = mIf ($3, ReverseTREE ($5), ReverseTREE ($7), $1);} .
  871.     Stats: Stats WHILE Expr DO Stats END ';'
  872.                  {$$ = mWhile ($3, ReverseTREE ($5), $1);} .
  873.     abstract grammar:
  874.     Stats           = Next: Stats REVERSE <
  875.        Empty        = .
  876.        If           = Expr Then: Stats Else: Stats .
  877.        While        = Expr Stats .
  878.     > .
  879.  
  880.  
  881. 2.11.2.  LL Parsers
  882.  
  883.      Using LL parsers a similar problem  as  in  the  LR  case  can  arise  if
  884. extended  BNF is used. Lists are parsed with an iteration which is turned into
  885. a loop statement as follows: (The identifiers Stats0, Stats1, Stat0, and Stat1
  886. in  the concrete grammar rules denote the symbolic access to the L-attribution
  887. mechanism provided by Ell [GrV88]. These identifiers should not  be  mixed  up
  888. with the similar ones used as node names in the abstract syntax.)
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.                                      Ast                                    13
  907.  
  908.  
  909. Example:
  910. concrete grammar (with tree building actions):
  911. Stats: {*Stats0=mStats0 ();} ( Stat ';' {*Stats0=mStats1 (Stat1, Stats0);} ) * .
  912. Stat : WHILE Expr DO Stats END {*Stat0=mWhile (Expr1, ReverseTREE (Stats1));} .
  913. abstract grammar:
  914. Stats           = <
  915.    Stats0       = .
  916.    Stats1       = Stat Stats REVERSE .
  917. > .
  918.  
  919. The list elements (statements) are inserted in  the  wrong  order  within  the
  920. first concrete grammar rule. The order is corrected by a call of the procedure
  921. ReverseTREE in the second concrete grammar rule.
  922.  
  923. 2.12.  Target Code
  924.  
  925.      An ast specification may include several  sections  containing  so-called
  926. target  code.  This sections follow the keywords TREE or SUBUNIT.  Target code
  927. is code written in the target language which is copied unchecked and unchanged
  928. to  certain  places  in the generated module.  It has to be enclosed in braces
  929. '{' '}'. Balanced braces within the target code are allowed. Unbalanced braces
  930. have  to be escaped by a preceding '\' character. In general, the escape char-
  931. acter '\' escapes everything within target code.   Therefore,  especially  the
  932. escape character itself has to be escaped.
  933.  
  934.     Example in C:
  935.     TREE SyntaxTree
  936.     IMPORT {# include "Idents.h" }
  937.     EXPORT {  typedef tSyntaxTree MyTree; }
  938.     GLOBAL {# include "Idents.h"
  939.               typedef struct { unsigned Line, Column; } tPosition;
  940.     BEGIN  { ... }
  941.     CLOSE  { ... }
  942.  
  943.  
  944.     Example in Modula-2:
  945.     TREE SyntaxTree
  946.     IMPORT { FROM Idents IMPORT tIdent; }
  947.     EXPORT { TYPE MyTree = tSyntaxTree; }
  948.     GLOBAL { FROM Idents IMPORT tIdent;
  949.              TYPE tPosition = RECORD Line, Column: CARDINAL; END; }
  950.     BEGIN  { ... }
  951.     CLOSE  { ... }
  952.  
  953.  
  954. The meaning of the sections is as follows:
  955.  
  956. IMPORT:     declarations to be included in the definition module  at  a  place
  957.             where IMPORT statements are legal.
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.                                      Ast                                    14
  969.  
  970.  
  971. EXPORT:     declarations to be included in the  definition  module  after  the
  972.             declaration of the tree type tTREE.
  973.  
  974. GLOBAL:     declarations to be included in the implementation module at global
  975.             level.
  976.  
  977. LOCAL:      same as GLOBAL within ast.
  978.  
  979. BEGIN:      statements to initialize the declared data structures.
  980.  
  981. CLOSE:      statements to finalize the declared data structures.
  982.  
  983. 2.13.  Common Node Fields
  984.  
  985.      Sometimes it is desirable to include certain record fields into all  node
  986. types.  This can be done directly in the target language by defining the macro
  987. TREE_NodeHead in the IMPORT or  EXPORT  target  code  sections.  These  fields
  988. become  members of the variant yyHead and they can be accessed as shown in the
  989. following examples:
  990.  
  991.     Example in C:
  992.     # define Tree_NodeHead int MyField1; MyType MyField2;
  993.     t->yyHead.MyField1 = ... ;
  994.  
  995.  
  996.     Example in Modula-2:
  997.     # define Tree_NodeHead MyField1: INTEGER; MyField2: MyType;
  998.     t^.yyHead.MyField1 := ... ;
  999.  
  1000.  
  1001. 2.14.  Type Specific Operations
  1002.  
  1003.      Procedures generated by ast apply several operations to attributes:  ini-
  1004. tialization,  finalization,  ascii  read and write, binary read and write, and
  1005. copy (see Table 3).  Initialization is performed whenever a node  is  created.
  1006. It  can  range  from  assigning  an initial value to the allocation of dynamic
  1007. storage or the construction of complex data structures.  Finalization is  per-
  1008. formed  immediately before a node is deleted and may e. g. release dynamically
  1009. allocated space. The read and write operations enable the readers and  writers
  1010. to  handle  the  complete  nodes including all attributes, even those of user-
  1011. defined types.  The operation copy is needed to duplicate values of attributes
  1012. of  user-defined  types. By default, ast just copies the bytes of an attribute
  1013. to duplicate it.  Therefore, pointer semantics is assumed for attributes of  a
  1014. pointer  type.   If value semantics is needed, the user has to take care about
  1015. this operation.  The operation equal checks whether two attributes are  equal.
  1016. It  is  used  as atomic operation for the procedure that tests the equality of
  1017. trees.
  1018.  
  1019.      The operations are type specific in the sense that every type has its own
  1020. set  of operations. All attributes having the same type (target type name) are
  1021. treated in the same way. Chosing different type names for one type  introduces
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.                                      Ast                                    15
  1033.  
  1034.  
  1035.  
  1036.                       Table 3: Type Specific Operations
  1037.  
  1038.                                                            default macro
  1039.   operation        macro name                      C                        Modula-2
  1040. ________________________________________________________________________________________
  1041. initialization   beginTYPE(a)
  1042. finalization     closeTYPE(a)
  1043. ascii read       readTYPE(a)       yyReadHex (& a, sizeof (a));         yyReadHex (a);
  1044. ascii write      writeTYPE(a)      yyWriteHex (& a, sizeof (a));        yyWriteHex (a);
  1045. binary read      getTYPE(a)        yyGet (& a, sizeof (a));             yyGet (a);
  1046. binary write     putTYPE(a)        yyPut (& a, sizeof (a));             yyPut (a);
  1047. copy             copyTYPE(a, b)
  1048. equal            equalTYPE(a, b)   memcmp (& a, & b, sizeof (a)) == 0   yyIsEqual (a, b)
  1049.               
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.                                 
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.                                                                      
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078. subtypes and allows to treat attributes  of  different  subtypes  differently.
  1079. Type  operations  for the predefined types of a target language are predefined
  1080. within ast (see Appendices 6 and  7).  For  user-defined  types,  ast  assumes
  1081. default  operations  (see  Table  3).  The procedures yyReadHex and yyWriteHex
  1082. read and write the bytes of an attribute  as  hexadecimal  values.   The  pro-
  1083. cedures  yyGet  and  yyPut  read and write the bytes of an attribute unchanged
  1084. (without conversion).  The operations are defined by a macro  mechanism.   The
  1085. procedure  yyIsEqual checks the bytes of two attributes for equality.  TYPE is
  1086. replaced by the concrete type name.  a is a formal macro  parameter  referring
  1087. to the attribute.  The predefined procedures mentioned in Table 3 use the glo-
  1088. bal variable yyf of type FILE * or IO.tFile [Gro87] describing the  file  used
  1089. by the readers and writers.
  1090.  
  1091.      It is possible to redefine the operations by including new macro  defini-
  1092. tions in the GLOBAL section. The following example demonstrates the syntax for
  1093. doing this. It shows how records of the type tPosition might  be  handled  and
  1094. how  subtypes  can  be  used  to  initialize  attributes of the same type dif-
  1095. ferently.
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.                                      Ast                                    16
  1125.  
  1126.  
  1127.     Example in C:
  1128.     IMPORT {
  1129.     # include "Sets.h"
  1130.     typedef struct { unsigned Line, Column; } tPosition;
  1131.     typedef tSet Set100;
  1132.     typedef tSet Set1000;
  1133.     }
  1134.     GLOBAL {
  1135.     # define begintPosition(a) a.Line = 0; a.Column = 0;
  1136.     # define readtPosition(a)  fscanf (yyf, "%d%d", & a.Line, & a.Column);
  1137.     # define writetPosition(a) fprintf (yyf, "%d %d", a.Line, a.Column);
  1138.     # define beginSet100(a)    MakeSet    (& a, 100);
  1139.     # define closeSet100(a)    ReleaseSet (& a);
  1140.     # define readSet100(a)     ReadSet    (yyf, & a);
  1141.     # define writeSet100(a)    WriteSet   (yyf, & a);
  1142.     # define beginSet1000(a)   MakeSet    (& a, 1000);
  1143.     # define closeSet1000(a)   ReleaseSet (& a);
  1144.     # define readSet1000(a)    ReadSet    (yyf, & a);
  1145.     # define writeSet1000(a)   WriteSet   (yyf, & a);
  1146.     }
  1147.  
  1148.  
  1149.     Example in Modula-2:
  1150.     IMPORT {
  1151.        FROM Sets      IMPORT tSet;
  1152.        TYPE tPosition = RECORD Line, Column: CARDINAL; END;
  1153.        TYPE Set100    = tSet;
  1154.        TYPE Set1000   = tSet;
  1155.     }
  1156.     GLOBAL {
  1157.        FROM IO        IMPORT ReadI, WriteI, WriteC;
  1158.        FROM Sets      IMPORT MakeSet, ReleaseSet, ReadSet, WriteSet;
  1159.     # define begintPosition(a) a.Line := 0; a.Column := 0;
  1160.     # define readtPosition(a)  a.Line := ReadI (yyf); a.Column := ReadI (yyf);
  1161.     # define writetPosition(a) WriteI (yyf, a.Line, 0); WriteC (yyf, ' '); \
  1162.                                WriteI (yyf, a.Column, 0);
  1163.     # define beginSet100(a)    MakeSet    (a, 100);
  1164.     # define closeSet100(a)    ReleaseSet (a);
  1165.     # define readSet100(a)     ReadSet    (yyf, a);
  1166.     # define writeSet100(a)    WriteSet   (yyf, a);
  1167.     # define beginSet1000(a)   MakeSet    (a, 1000);
  1168.     # define closeSet1000(a)   ReleaseSet (a);
  1169.     # define readSet1000(a)    ReadSet    (yyf, a);
  1170.     # define writeSet1000(a)   WriteSet   (yyf, a);
  1171.     }
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.                                      Ast                                    17
  1186.  
  1187.  
  1188. 2.15.  Storage Management
  1189.  
  1190.      The storage  management  for  the  nodes  to  be  created  is  completely
  1191. automatic.   Usually, the user does not have to care about it.  The predefined
  1192. storage management works as follows: Every generated tree module contains  its
  1193. own  heap  manager which is designed in favour of speed.  The constructor pro-
  1194. cedures use an in-line code sequence to obtain storage (see below).  The  heap
  1195. manager does not maintain free lists. It only allows to free the complete heap
  1196. of  one  module  using  the  procedure   ReleaseTREEModule.    The   procedure
  1197. ReleaseTREE  does not free the node space, it only finalizes the attributes of
  1198. the node.
  1199.  
  1200.      To change the predefined behaviour, two macro definitions may be included
  1201. in the GLOBAL section. For C these macros are initialized as follows:
  1202.  
  1203.     # define yyALLOC(ptr, size) \
  1204.       if ((ptr = (tTREE) TREE_PoolFreePtr) >= (tTREE) TREE_PoolMaxPtr) \
  1205.          ptr = TREE_Alloc (); \
  1206.       TREE_PoolFreePtr += size;
  1207.     # define yyFREE(ptr, size)
  1208.  
  1209. For Modula-2 these macros are initialized as follows:
  1210.  
  1211.     # define yyALLOC(ptr, size) ptr := yyPoolFreePtr; \
  1212.       IF SYSTEM.ADDRESS (ptr) >= yyPoolMaxPtr THEN ptr := yyAlloc (); END; \
  1213.       INC (yyPoolFreePtr, size);
  1214.     # define yyFREE(ptr, size)
  1215.  
  1216. The following lines switch the heap manager to a global storage allocator with
  1217. free lists:
  1218.  
  1219.     # define yyALLOC(ptr, size) ptr = Alloc (size);
  1220.     # define yyFREE(ptr, size)  Free (size, ptr);
  1221.  
  1222. Now ReleaseTREE will work as expected whereas ReleaseTREEModule does not  work
  1223. any more.
  1224.  
  1225. 3.  About the Generated Program Module
  1226.  
  1227.      A specification as described in the previous section is translated by ast
  1228. into  a  program module consisting of a definition and an implementation part.
  1229. Only the definition part or header file respectively is sketched here
  1230.  Appendices 4 and 5 contain the general schemes.  The definition part contains
  1231. primarily  type  declarations  to  describe the structure of the trees and the
  1232. headings of the generated procedures.
  1233.  
  1234.      Every node type is turned into a constant declaration  and  a  struct  or
  1235. record  declaration.   That  is  quite  simple,  because node types and record
  1236. declarations are almost the same concepts except for the  extension  mechanism
  1237. and  some  shorthand  notations.   All these records become members of a union
  1238. type or a variant record used to describe tree nodes in general. This  variant
  1239. record  has a tag field called Kind which stores the code of the node type.  A
  1240. pointer to the  variant  record  is  a  type  representing  trees.   Like  all
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.                                      Ast                                    18
  1252.  
  1253.  
  1254. generated  names, this pointer type is derived from the name of the specifica-
  1255. tion.  Table 4 briefly explains the exported objects (replace TREE by the name
  1256. of  the  generated module (see section 2.12.) and <node type> by all the names
  1257. of node types).  Whereas in Modula-2 the names of the constants  to  code  the
  1258. node  types and the names of the record variants are identical to the names of
  1259. the node types this is not the case in C.  In C only the names  of  the  union
  1260. members  are  identical,  the  constant names are prefixed with the letter 'k'
  1261. standing for Kind.
  1262.  
  1263.      The parameters of the procedures m<nodetype> have  to  be  given  in  the
  1264. order  of  the  input  attributes in the specification. Attributes of the base
  1265. type (recursively) precede the ones  of  the  derived  type.   The  procedures
  1266. TraverseTREETD  and  TraverseTREEBU  visit  all  nodes  of  a  tree or a graph
  1267.  
  1268.                   Table 4: Generated Objects and Procedures
  1269.  
  1270. object/procedure    description
  1271. _________________________________________________________________________________________
  1272. k<node type>        named constant to encode a node type in C
  1273. <node type>         named constant to encode a node type in Modula-2
  1274. <node type>         name of union member or record variant for a node type
  1275. tTREE               pointer type, refers to variant record type describing all node types
  1276. TREERoot            variable of type tTREE, can serve as root
  1277.                     (additional variables can be declared)
  1278. TREE_NodeName       array mapping node types to names (strings) in C
  1279. TREE_NodeSize       array mapping node types to the size of the nodes in C
  1280. yyNodeSize          array mapping node types to the size of the nodes in Modula-2
  1281. _________________________________________________________________________________________
  1282. MakeTREE            node constructor procedure without attribute initialization
  1283. IsType              test a node for a certain type
  1284. n<node type>        node constructor procedures with attribute initialization
  1285.                     according to the type specific operations
  1286. m<node type>        node constructor procedures with attribute initialization
  1287.                     from a parameter list for input attributes
  1288. ReleaseTREE         node or graph finalization procedure,
  1289.                     all attributes are finalized, all node space is deallocated
  1290. ReleaseTREEModule   deallocation of all graphs managed by a module
  1291. WriteTREENode       ASCII node writer procedure
  1292. ReadTREE            ASCII graph reader procedure
  1293. WriteTREE           ASCII graph writer procedure
  1294. GetTREE             binary graph reader procedure
  1295. PutTREE             binary graph writer procedure
  1296. ReverseTREE         procedure to reverse lists
  1297. TraverseTREETD      top down graph traversal procedure (reverse depth first)
  1298. TraverseTREEBU      bottom up graph traversal procedure (depth first search)
  1299. CopyTREE            graph copy procedure
  1300. IsEqualTREE         equality test procedure for trees
  1301. CheckTREE           graph syntax checker procedure
  1302. QueryTREE           graph browser procedure
  1303. BeginTREE           procedure to initialize user-defined data structures
  1304. CloseTREE           procedure to finalize user-defined data structures
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.                                      Ast                                    19
  1318.  
  1319.  
  1320. respectively. At every node a procedure given as  parameter  is  executed.  An
  1321. assignment  of  a tree or graph to a variable of type tTREE can be done in two
  1322. ways: The usual assignment operators '=' or ':=' yield pointer semantics.  The
  1323. procedure CopyTREE yields value semantics by duplicating a given graph.
  1324.  
  1325.      The procedure QueryTREE allows to browse a tree and to inspect  one  node
  1326. at  a  time. A node including the values of its attributes is printed on stan-
  1327. dard output.  Then the user is prompted to provide one of the  following  com-
  1328. mands from standard input:
  1329.  
  1330.     parent          display parent node
  1331.     quit            quit procedure QueryTREE
  1332.     <selector>      display specified child (first match, abbreviation possible)
  1333.     <selector><space>display specified child (exact match, no abbreviation)
  1334.  
  1335. All commands can be abbreviated to an unambiguous  prefix.  Usually,  a  first
  1336. match  strategy  is  used to determine a child from its (abbreviated) selector
  1337. name. With this search strategy, children whose name is a prefix of others may
  1338. not be accessible. If an unabbreviated selector name is supplied together with
  1339. a following space character an exact match strategy is used, which  allows  to
  1340. access every child. The empty command behaves like parent.
  1341.  
  1342.      The construction of the pointer and the union type above does not enforce
  1343. the tree typing rules through the types of the target language. In fact, it is
  1344. possible to construct trees  that  violate  the  specification.  The  user  is
  1345. responsible  to  adhere to the type rules. Most of the generated procedures do
  1346. not care about the type rules. Moreover, type violations are possible and such
  1347. erroneous trees are handled correctly by all procedures.  The procedure Check-
  1348. TREE can be used to check if a tree is  properly  typed.  In  case  of  typing
  1349. errors the involved parent and child nodes are printed on standard error.
  1350.  
  1351.      The binary graph writer procedure GetTREE produces a binary file contain-
  1352. ing  the  graph in linearized form. The nodes are written according to a depth
  1353. first traversal. Edges are either represented by concatenation of nodes or  by
  1354. symbolic  (integer)  labels.   The  following  kinds of records specified by C
  1355. types are written to the file:
  1356.  
  1357.     # define yyNil          0374
  1358.     # define yyNoLabel      0375
  1359.     # define yyLabelDef     0376
  1360.     # define yyLabelUse     0377
  1361.  
  1362.     typedef unsigned char  TREE_tKind;   /* less than 252 node types */
  1363.     typedef unsigned short TREE_tKind;   /* more than 251 node types */
  1364.     typedef unsigned short TREE_tLabel;
  1365.  
  1366.     struct { char yyNil     ;                               } NoTree;
  1367.     struct { char yyLabelUse; TREE_tLabel <label>;          } LabelUse;
  1368.     struct { char yyLabelDef; TREE_tLabel <label>;
  1369.                               TREE_tKind Kind; <attributes> } LabelDef;
  1370.     struct { char yyNoLabel ; TREE_tKind Kind; <attributes> } NoLabel;
  1371.     struct { char Kind      ; <attributes>                  } Kind;
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.                                      Ast                                    20
  1383.  
  1384.  
  1385. Record fields whose name starts with yy have  a  constant  value  as  defined.
  1386. <label>  is an integer representing a certain address.  <attributes> are writ-
  1387. ten with the type specific put macros which either copy the bytes of an attri-
  1388. bute  unchanged or do whatever the user has specified. If the value of the tag
  1389. field Kind is less than 252 then the format Kind is used, otherwise the format
  1390. NoLabel is used to write unlabeled nodes.
  1391.  
  1392. 4.  Using the Generated Program Module
  1393.  
  1394.      This section explains how to use the objects  of  the  generated  program
  1395. module.  Trees or graphs are created by successively creating their nodes. The
  1396. easiest way is to call the constructor procedures m<node_type>. These  combine
  1397. node  creation,  storage allocation, and attribute assignment.  They provide a
  1398. mechanism similar to record aggregates. Nested calls of constructor procedures
  1399. allow  programming  with  (ground)  terms as in Prolog or LISP.  In general, a
  1400. node can be created by a call of one of the procedures
  1401.  
  1402.     MakeTREE, n<node type>, or m<node type>.
  1403.  
  1404. The type of a node can be retrieved by examination of the predefined tag field
  1405. called  Kind.  Alternatively the function IsType can be used to test whether a
  1406. node has a certain type or a subtype thereof.  Children and attributes can  be
  1407. accessed  using two record selections.  The first one states the node type and
  1408. the second one gives the selector name of the desired item.
  1409.  
  1410.     Example in C:
  1411.     abstract syntax:
  1412.     Expr         = [Pos: tPosition] <
  1413.        Binary    = Lop: Expr Rop: Expr [Operator: int] .
  1414.        Unary     = Expr [Operator] .
  1415.        IntConst  = [Value] .
  1416.        RealConst = [Value: float] .
  1417.     > .
  1418.  
  1419.  
  1420.     tree construction by a term:
  1421.     # define Plus 1
  1422.     tTREE t;
  1423.     tPosition Pos;
  1424.     t = mBinary (Pos, mIntConst (Pos, 2), mIntConst (Pos, 3), Plus);
  1425.  
  1426.  
  1427.     tree construction during parsing:
  1428.     Expr: Expr '+' Expr {$$.Tree = mBinary ($2.Pos, $1.Tree, $3.Tree, Plus);} .
  1429.     Expr:      '-' Expr {$$.Tree = mUnary  ($1.Pos, $2.Tree, Minus);        } .
  1430.     Expr: IntConst      {$$.Tree = mIntConst ($1.Pos, $1.IntValue);         } .
  1431.     Expr: RealConst     {$$.Tree = mRealConst ($1.Pos, $1.RealValue);       } .
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.                                      Ast                                    21
  1446.  
  1447.  
  1448.     tree construction using a statement sequence:
  1449.     t = MakeTREE (Binary);
  1450.     t->Binary.Pos.Line            = 0;
  1451.     t->Binary.Pos.Column          = 0;
  1452.     t->Binary.Lop                 = MakeTREE (IntConst);
  1453.     t->Binary.Lop->IntConst.Pos   = Pos;
  1454.     t->Binary.Lop->IntConst.Value = 2;
  1455.     t->Binary.Rop                 = MakeTREE (IntConst);
  1456.     t->Binary.Rop->IntConst.Pos   = Pos;
  1457.     t->Binary.Rop->IntConst.Value = 3;
  1458.     t->Binary.Operator            = Plus;
  1459.  
  1460.  
  1461.     access of tag field, children, and attributes:
  1462.     switch (t->Kind) {
  1463.     case kExpr  : ... t->Expr.Pos             ...
  1464.     case kBinary: ... t->Binary.Operator      ...
  1465.                   ... t->Binary.Lop           ...
  1466.     case kUnary : ... t->Unary.Expr->Expr.Pos ...
  1467.     };
  1468.  
  1469.  
  1470.     Example in Modula-2:
  1471.     abstract syntax:
  1472.     Expr         = [Pos: tPosition] <
  1473.        Binary    = Lop: Expr Rop: Expr [Operator: INTEGER] .
  1474.        Unary     = Expr [Operator] .
  1475.        IntConst  = [Value] .
  1476.        RealConst = [Value: REAL] .
  1477.     > .
  1478.  
  1479.  
  1480.     tree construction by a term:
  1481.     CONST Plus = 1;
  1482.     VAR t: tTREE; Pos: tPosition;
  1483.     t := mBinary (Pos, mIntConst (Pos, 2), mIntConst (Pos, 3), Plus);
  1484.  
  1485.  
  1486.     tree construction during parsing:
  1487.     Expr: Expr '+' Expr {$$.Tree := mBinary ($2.Pos, $1.Tree, $3.Tree, Plus);} .
  1488.     Expr:      '-' Expr {$$.Tree := mUnary  ($1.Pos, $2.Tree, Minus);        } .
  1489.     Expr: IntConst      {$$.Tree := mIntConst ($1.Pos, $1.IntValue);         } .
  1490.     Expr: RealConst     {$$.Tree := mRealConst ($1.Pos, $1.RealValue);       } .
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507.                                      Ast                                    22
  1508.  
  1509.  
  1510.     tree construction using a statement sequence:
  1511.     t := MakeTREE (Binary);
  1512.     t^.Binary.Pos.Line            := 0;
  1513.     t^.Binary.Pos.Column          := 0;
  1514.     t^.Binary.Lop                 := MakeTREE (IntConst);
  1515.     t^.Binary.Lop^.IntConst.Pos   := Pos;
  1516.     t^.Binary.Lop^.IntConst.Value := 2;
  1517.     t^.Binary.Rop                 := MakeTREE (IntConst);
  1518.     t^.Binary.Rop^.IntConst.Pos   := Pos;
  1519.     t^.Binary.Rop^.IntConst.Value := 3;
  1520.     t^.Binary.Operator            := Plus;
  1521.  
  1522.  
  1523.     access of tag field, children, and attributes:
  1524.     CASE t^.Kind OF
  1525.     | Expr  : ... t^.Expr.Pos             ...
  1526.     | Binary: ... t^.Binary.Operator      ...
  1527.               ... t^.Binary.Lop           ...
  1528.     | Unary : ... t^.Unary.Expr^.Expr.Pos ...
  1529.     END;
  1530.  
  1531.  
  1532. 5.  Related Research
  1533.  
  1534. 5.1.  Variant Records
  1535.  
  1536.      Ast specifications and variant record types like in  Pascal  or  Modula-2
  1537. are  very  similar.  Every  node type in an ast specification corresponds to a
  1538. single variant. In the generated code every node type  is  translated  into  a
  1539. record  type.  All  record  types  become  members  of  a  variant record type
  1540. representing the type for the trees.
  1541.  
  1542.      The differences are the following: Ast specifications  are  shorter  than
  1543. directly  hand-written  variant record types.  Ast specifications are based on
  1544. the formalism of context-free grammars (see section 5.3.). The  generator  ast
  1545. automatically  provides  operations  on record types which would be simple but
  1546. voluminous to program by hand. The node constructor procedures allow to  write
  1547. record  aggregates  and  provide  dynamic  storage  management. The reader and
  1548. writer procedures supply input and output for record types and even  for  com-
  1549. plete linked data structures such as trees and graphs.
  1550.  
  1551. 5.2.  Type Extensions
  1552.  
  1553.      Type  extensions  have  been  introduced   with   the   language   Oberon
  1554. [Wir88a,Wir88b,Wir88c].   The extension mechanism of ast is basically the same
  1555. as in  Oberon.  The  notions  extension,  base  type,  and  derived  type  are
  1556. equivalent.  Type tests and type guards can be easily programmed by inspecting
  1557. the tag field of a node.  Ast does not provide assignment of subtypes to  base
  1558. types in the sense of value semantics or a projection, respectively.  The tool
  1559. can be seen as a preprocessor providing type extensions for Modula-2 and C.
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.                                      Ast                                    23
  1572.  
  1573.  
  1574.      The second example in section 2.5. illuminates the  relationship  between
  1575. ast  and  Oberon.  The node type Stats is a base type with two fields, a child
  1576. and an attribute.  It is extended e. g. by the node type While with  two  more
  1577. fields which are children.
  1578.  
  1579. 5.3.  Context-Free Grammars
  1580.  
  1581.      As already mentioned, ast specifications are based on context-free  gram-
  1582. mars.   Ast  specifications extend context-free grammars by selector names for
  1583. right-hand side symbols, attributes, the extension mechanism, and modules.  If
  1584. these features are omitted, we basically arrive at context-free grammars. This
  1585. holds from the syntactic as well as from the semantic point of view. The names
  1586. of  the  node  types  represent  both terminal or nonterminal symbols and rule
  1587. names.  Node types correspond to grammar rules. The notions of derivation  and
  1588. derivation tree can be used similarly in both cases. The selector names can be
  1589. seen as syntactic sugar and the attributes as some kind of  terminal  symbols.
  1590. The  extension  mechanism  is equivalent to a shorthand notation for factoring
  1591. out common rule parts in combination with implicit chain rules.
  1592.  
  1593.     Example:
  1594.     ast specification:
  1595.     Stats           = Next: Stats <
  1596.        If           = Expr Then: Stats Else: Stats .
  1597.        While        = Expr Stats .
  1598.     > .
  1599.  
  1600.  
  1601.     corresponding context-free grammar:
  1602.     Stats           = Stats .
  1603.     Stats           = Stats If .
  1604.     Stats           = Stats While .
  1605.     If              = Expr Stats Stats .
  1606.     While           = Expr Stats .
  1607.  
  1608.  
  1609.      In the example above, Stats corresponds to a nonterminal.  There are  two
  1610. rules  or right-hand sides for Stats which are named If and While.  The latter
  1611. would be regarded as nonterminals, too, if a child of types If or While  would
  1612. be specified.
  1613.  
  1614. 5.4.  Attribute Grammars
  1615.  
  1616.      Attribute grammars [Knu68,Knu71] and  ast  specifications  are  based  on
  1617. context-free  grammars and associate attributes with terminal and nonterminals
  1618. symbols. Additionally ast allows attributes which are local to rules.  As  the
  1619. structure  of  the  tree  itself  is  known  and  transparent, subtrees can be
  1620. accessed or created dynamically and used as attribute values.  The  access  of
  1621. the  right-hand  side  symbols  uses  the  selector  names for symbolic access
  1622. instead of the grammar symbol with an additional subscript if  needed.   There
  1623. is no need to map chain rules to tree nodes because of the extension mechanism
  1624. offered by ast.  Attribute evaluation is outside the scope of ast.   This  can
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.                                      Ast                                    24
  1636.  
  1637.  
  1638. be  done either with the attribute evaluator generator ag [Gro89] which under-
  1639. stands  ast  specifications  extended  by  attribute  computation  rules   and
  1640. processes  the  trees generated by ast or by hand-written programs that use an
  1641. ast generated module. In the latter case attribute computations do not have to
  1642. obey the single assignment restriction for attributes. They can assign a value
  1643. to an attribute zero, one, or several times.
  1644.  
  1645. 5.5.  Interface Description Language (IDL)
  1646.  
  1647.      The approach of ast is similar to the one  of  IDL  [Lam87,NNG89].   Both
  1648. specify attributed trees as well as graphs.  Node types without extensions are
  1649. called nodes in IDL and node types with extensions  (base  types)  are  called
  1650. classes.  Ast has simplified this to the single notion of a node type.  Attri-
  1651. butes are treated similarly in both systems.  Children and attributes are both
  1652. regarded  as attributes, as structural and non-structural ones, with only lit-
  1653. tle difference in between.  Both systems allow multiple inheritance of  attri-
  1654. butes,  ast  has  a separate syntax for single inheritance and uses the notion
  1655. extension instead [Wir88c].  IDL knows the predefined types INTEGER, RATIONAL,
  1656. BOOLEAN,  STRING,  SEQ  OF,  and  SET OF. It offers special operations for the
  1657. types SEQ OF and SET OF.  Ast really has no built in types at all, it uses the
  1658. ones  of  the  target  language  and  has a table containing the type specific
  1659. operations e. g. for reading and writing.  Both ast and IDL  allow  attributes
  1660. of  user-defined types. In ast, the type specific operations for predefined or
  1661. user-defined types are easily expressed by macros using  the  target  language
  1662. directly.  IDL offers an assertion language whereas ast does not. IDL provides
  1663. a mechanism to modify existing specifications.  The module feature of ast  can
  1664. be  used to extend existing specifications.  From ast, readers and writers are
  1665. requested with simple command line options instead  of  complicated  syntactic
  1666. constructs.   Ast  does  not  support  representation  specifications, because
  1667. representations are much more easily expressed using the types of  the  target
  1668. language  directly.  Summarizing, we consider ast to have a simpler specifica-
  1669. tion method and to generate more powerful features like  aggregates,  reversal
  1670. of lists, and graph browsers.
  1671.  
  1672. 5.6.  Attribute Coupled Grammars
  1673.  
  1674.      Attribute coupled grammars (ACG's) [Gie88]  or  algebraic  specifications
  1675. [HHK88] have only very little in common with ast specifications. They all view
  1676. node types or rules as signatures of functions. The  name  of  the  node  type
  1677. plays  the  role of the function name and describes the result type. The types
  1678. of the children and attributes correspond to the type of  the  function  argu-
  1679. ments.  The constructor procedures generated by ast reflect this view best.
  1680.  
  1681. 5.7.  Object-Oriented Languages
  1682.  
  1683.      The extension mechanism of ast is exactly the same as single  inheritance
  1684. in  object-oriented  languages like e. g. Simula [DMN70] or Smalltalk [Gol84].
  1685. The hierarchy introduced by the extension mechanism  corresponds  directly  to
  1686. the  class  hierarchy of object-oriented languages.  The notions base type and
  1687. super class both represent the same concept.  Messages and virtual  procedures
  1688. are  out  of  the  scope  of  ast.  Virtual procedures might be simulated with
  1689. procedure-valued attributes.  Table 5 summarizes the corresponding notions  of
  1690. trees (ast), type extensions, and object-oriented programming.
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.                                      Ast                                    25
  1702.  
  1703.  
  1704.  
  1705. Table 5: Comparison of notions from the areas of trees, types, and object-oriented programming
  1706.  
  1707.        trees              types             object-oriented programming
  1708.        ________________________________________________________________
  1709.        node type          record type       class
  1710.        -                  base type         superclass
  1711.        -                  derived type      subclass
  1712.        attribute, child   record field      instance variable
  1713.        tree node          record variable   object, instance
  1714.        -                  extension         inheritance
  1715.                        
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.                                          
  1722.  
  1723.  
  1724.  
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730. 5.8.  Tree Grammars
  1731.  
  1732.      Conventional tree grammars are characterized by the fact that all  right-
  1733. hand  sides start with a terminal symbol. They are used for the description of
  1734. string languages that represent trees  in  prefix  form.   Ast  specifications
  1735. describe  trees   which  are represented by (absolute) pointers from parent to
  1736. child nodes. If we shift the names of node types of ast specifications to  the
  1737. beginning  of the right-hand side and interpret them as terminals we arrive at
  1738. conventional tree grammars. That is exactly what is done by the ast tree/graph
  1739. writers. They write a tree in prefix form and prepend every node with the name
  1740. of its node type.  That is necessary to be able to  perform  the  read  opera-
  1741. tions.
  1742.  
  1743. 6.  Hints on Specifying Abstract Syntax
  1744.  
  1745. -    Keep the abstract syntax as short and simple as possible.
  1746.  
  1747. -    Try to normalize by representing only the most general form.
  1748.  
  1749. -    Normalize to the general form e. g. by adding default values.
  1750.  
  1751. -    Normalize several concrete representations to one abstract construct.
  1752.  
  1753. -    Map concrete to abstract syntax by disregarding the concrete syntax rules
  1754.      and by concentrating on the semantic structure of the abstract syntax.
  1755.  
  1756. -    Map several concrete nonterminals to one abstract node type (e. g.  Expr,
  1757.      Term, and Factor -> Expr)
  1758.  
  1759. -    Allow all lists to be empty regardless of the concrete syntax.  Otherwise
  1760.      you  have  to  process the list element at two places in exactly the same
  1761.      way. This causes programming overhead and violates the law  of  singular-
  1762.      ity: "One thing only once!"
  1763.  
  1764. -    Operators can be represented by different node types (e. g. Plus,  Minus,
  1765.      Mult,  ...) or by one node type with an attribute describing the operator
  1766.      (e. g. Binary).
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.                                      Ast                                    26
  1780.  
  1781.  
  1782. -    Lists can be represented by separate nodes for the list and the  elements
  1783.      (e.  g. Stats and Stat) or by nodes for the elements where every node has
  1784.      a child that refers to the next list element (see last example in section
  1785.      2.11.1.).
  1786.  
  1787. 7.  Examples
  1788.  
  1789.      The Appendices 1 to 3 contain examples of ast specifications.
  1790.  
  1791.      Appendix 1 contains the concrete syntax of ast's specification  language.
  1792. The  node  types enclosed in quotes or starting with the character 't' consti-
  1793. tute the terminals for ast's parser. The extensions and the  node  types  used
  1794. for the latter describe the lexical grammar.
  1795.  
  1796.      Appendix 2 contains the concrete syntax of a  small  example  programming
  1797. language  called  MiniLAX  [GrK88].   The  attributes specified are the ones a
  1798. parser would evaluate during parsing.  The Appendices 1 and 2  show  how  con-
  1799. crete grammars can be described with ast.
  1800.  
  1801.      Appendix 3 contains an  abstract  syntax  for  MiniLAX.   The  attributes
  1802. specified  are  input  or intrinsic ones whose values would be provided by the
  1803. scanner and parser.  The definition follows the hints of the previous section.
  1804. Terminal  symbols without attributes are omitted.  All binary and unary opera-
  1805. tors are expressed by two nodes having one attribute to represent  the  opera-
  1806. tor.  To simplify things as much as possible all lists are allowed to be empty
  1807. and procedure declarations as well as calls always have a parameter list.  The
  1808. specification  tries  to  keep the tree as small as possible.  The inheritance
  1809. mechanism allows to avoid all chain rules. There are no nodes for sequences of
  1810. declarations,  statements,  etc..  Instead  every  node for a declaration or a
  1811. statement has a field named Next describing the successor entity.  Except  for
  1812. expressions  no  separate  nodes  are used for identifiers. The information is
  1813. included as attribute in the node types Proc,  Var,  Formal,  and  Call.   The
  1814. source  position  is  stored only at the nodes where it might be needed during
  1815. semantic analysis. The above measures not only reduce the  amount  of  storage
  1816. but  they also reduce run time because less information has to be produced and
  1817. processed.
  1818.  
  1819. 8.  Experiences
  1820.  
  1821.      Ast can be used not only for abstract syntax trees in compilers  but  for
  1822. every  tree  or  graph  like data structure. In general the data structure can
  1823. serve as interface between phases within a program or  between  separate  pro-
  1824. grams.   In the latter case it would be communicated via a file using the gen-
  1825. erated reader and writer procedures.
  1826.  
  1827.      Generated tree respectively graph modules have successfully been used  in
  1828. compilers  e. g. for MiniLAX [WGS89] and UNITY [Bie89] as well as for a Modula
  1829. to C translator [Mar90].  The modules for the internal data structure  of  ast
  1830. itself  and  the  attribute evaluator generator ag [Gro89] have also been gen-
  1831. erated by ast.  Moreover, the symbol table module of the Modula to C  transla-
  1832. tor has been generated.
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843.  
  1844.                                      Ast                                    27
  1845.  
  1846.  
  1847.      The advantage of this approach is that it saves considerably  hand-coding
  1848. of  trivial  declarations  and operations. Table 6 lists the sizes (numbers of
  1849. lines) of some specifications and the generated modules.  Sums in the specifi-
  1850. cation  column  are composed of the sizes for the definition of node types and
  1851. for user-supplied target code.  Sums in the tree module column are composed of
  1852. the sizes for the definition part and for the implementation part.  The reason
  1853. for the large sizes of the tree modules comes from the numerous node construc-
  1854. tor procedures and from the graph browser in the case of ag.  These procedures
  1855. proved to be very helpful for debugging purposes as they provide readable out-
  1856. put  of  complex  data  structures.  The constructor procedures allow to write
  1857. record aggregates. Therefore, node creation and assignment of  values  to  the
  1858. components can be written very compact.  It is even possible to write (ground)
  1859. terms as in Prolog or LISP by nested calls of the constructor procedures.
  1860.  
  1861.                     Table 6: Examples of Ast Applications
  1862.  
  1863.             application         specification         tree module
  1864.             _____________________________________________________
  1865.             MiniLAX                  56         202 +  835 = 1037
  1866.             Modula-2                240         583 + 3083 = 3666
  1867.             UNITY                   210         207 +  962 = 1169
  1868.             Ag                 78 + 347 = 425   317 + 1317 = 1634
  1869.             Definition table   82 + 900 = 982   399 + 1431 = 1830
  1870.                             
  1871.  
  1872.  
  1873.  
  1874.  
  1875.                                              
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884. 9.  Usage
  1885.  
  1886. NAME
  1887.    ast - generator for abstract structure/syntax trees
  1888. SYNOPSIS
  1889.    ast [-options] [-ldir] [file]
  1890. DESCRIPTION
  1891.    Ast generates a program module to handle  arbitrary  attributed  trees  and
  1892.    graphs.   A  typical application is the abstract syntax tree in a compiler.
  1893.    The input file contains a specification which describes  the  structure  of
  1894.    all  possible  trees or nodes respectively and the attributes of the nodes.
  1895.    Ast generates type declarations to implement  the  tree  and  several  pro-
  1896.    cedures  for tree manipulation including ASCII and binary readers and writ-
  1897.    ers (see options below).  If file is omitted the specification is read from
  1898.    standard input.
  1899. OPTIONS
  1900.  
  1901. a    generate all except -ch (default)
  1902.  
  1903. n    generate node constructorsprocedures n<node> (node)
  1904.  
  1905. m    generate node constructorsprocedures m<node> (make)
  1906.  
  1907.  
  1908.  
  1909.  
  1910.  
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.                                      Ast                                    28
  1917.  
  1918.  
  1919. f    generate node/tree destroyerprocedure ReleaseTREE (free)
  1920.  
  1921. F    generate general destroyerprocedure ReleaseTREEModule (FREE)
  1922.  
  1923. o    generate ASCII node writerprocedure WriteTREENode (output)
  1924.  
  1925. r    generate ASCII graph readerprocedure ReadTREE
  1926.  
  1927. w    generate ASCII graph writerprocedure WriteTREE
  1928.  
  1929. g    generate binary graph readerprocedure GetTREE
  1930.  
  1931. p    generate binary graph writerprocedure PutTREE
  1932.  
  1933. R    generate list reverser   procedure ReverseTREE
  1934.  
  1935. t    generate top down traversalprocedure TraverseTREETD
  1936.      (reverse depth first)
  1937.  
  1938. b    generate bottom up traversalprocedure TraverseTREEBU
  1939.      (depth first)
  1940.  
  1941. y    generate graph copy      procedure CopyTREE
  1942.  
  1943. =    generate tree equality testprocedure IsEqualTREE
  1944.  
  1945. k    generate graph checker   procedure CheckTREE
  1946.  
  1947. q    generate graph browser   procedure QueryTREE
  1948.  
  1949. d    generate definition module
  1950.  
  1951. i    generate implementation module
  1952.  
  1953. s    generate import statements
  1954.  
  1955. 4    generate tree/graph description in file VIEW.TS
  1956.  
  1957. 6    generate # line directives
  1958.  
  1959. 7    touch output files only if necessary
  1960.  
  1961. 8    report storage consumption
  1962.  
  1963. c    generate C code (default is Modula-2)
  1964.  
  1965. h    print help information
  1966.  
  1967. ldir dir is the directory where ast finds its table files
  1968.   FILES
  1969.      if output is in C:
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.                                      Ast                                    29
  1981.  
  1982.  
  1983.      <module>.h          specification of the generated graph module
  1984.      <module>.c          body of the generated graph module
  1985.      yy<module>.w        macro file defining type specific operations
  1986.      if output is in Modula-2:
  1987.      <module>.md         definition module of the generated graph module
  1988.      <module>.mi         implementation module of the generated graph module
  1989.      <module>.imp        import statements
  1990.   SEE ALSO
  1991.      J.  Grosch:  "Ast  -  A  Generator  for  Abstract  Syntax   Trees",   GMD
  1992.      Forschungsstelle  an  der  Universitaet  Karlsruhe,  Compiler  Generation
  1993.      Report No. 15
  1994.      J. Grosch: "Tool Support for Data  Structures",  Structured  Programming,
  1995.      12, 31-38 (1991)
  1996.  
  1997. References
  1998.  
  1999. [Bie89]
  2000.      F. Bieler, An Interpreter for Chandy/Misra's UNITY, internal  paper,  GMD
  2001.      Forschungsstelle an der Universitat Karlsruhe, 1989.
  2002.  
  2003. [DMN70]
  2004.      O. Dahl, B. Myrhaug and K. Nygaard, SIMULA  67  Common  Base  Language  -
  2005.      Publication S-22, Norwegian Computing Center, Oslo, 1970.
  2006.  
  2007. [Gie88]
  2008.      R. Giegerich, Composition and Evaluation of Attribute  Coupled  Grammars,
  2009.      Acta Inf. 25, (1988), 355-423.
  2010.  
  2011. [Gol84]
  2012.      A.  Goldberg,  Smalltalk-80:  The  Interactive  Programming  Environment,
  2013.      Addison Wesley, Reading, MA, 1984.
  2014.  
  2015. [Gro87]
  2016.      J. Grosch, Reusable Software - A Collection of  Modula-Modules,  Compiler
  2017.      Generation   Report  No.  4,  GMD  Forschungsstelle  an  der  Universitat
  2018.      Karlsruhe, Sep. 1987.
  2019.  
  2020. [GrK88]
  2021.      J. Grosch and  E.  Klein,  Ubersetzerbau-Praktikum,  Compiler  Generation
  2022.      Report  No.  9,  GMD  Forschungsstelle an der Universitat Karlsruhe, June
  2023.      1988.
  2024.  
  2025. [GrV88]
  2026.      J. Grosch and B. Vielsack, The Parser Generators Lalr and  Ell,  Compiler
  2027.      Generation   Report  No.  8,  GMD  Forschungsstelle  an  der  Universitat
  2028.      Karlsruhe, Apr. 1988.
  2029.  
  2030. [Gro88]
  2031.      J. Grosch, Generators for High-Speed Front-Ends, LNCS 371,  (Oct.  1988),
  2032.      81-92, Springer Verlag.
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.  
  2043.                                      Ast                                    30
  2044.  
  2045.  
  2046. [Gro89]
  2047.      J. Grosch, Ag - An Attribute  Evaluator  Generator,  Compiler  Generation
  2048.      Report  No.  16,  GMD Forschungsstelle an der Universitat Karlsruhe, Aug.
  2049.      1989.
  2050.  
  2051. [Gro91]
  2052.      J. Grosch, Puma - A Generator for the Transformation of Attributed Trees,
  2053.      Compiler   Generation   Report   No.  26,  GMD  Forschungsstelle  an  der
  2054.      Universitat Karlsruhe, July 1991.
  2055.  
  2056. [HHK88]
  2057.      J. Heering, P. R. H.  Hendriks,  P.  Klint  and  J.  Rekers,  The  Syntax
  2058.      Definition  Formalism  SDF  - Reference Manual, ESPRIT Project GIPE, Dec.
  2059.      1988.
  2060.  
  2061. [Joh75]
  2062.      S. C. Johnson, Yacc -  Yet Another  Compiler-Compiler,  Computer  Science
  2063.      Technical  Report  32, Bell Telephone Laboratories, Murray Hill, NJ, July
  2064.      1975.
  2065.  
  2066. [Knu68]
  2067.      D. E. Knuth, Semantics of Context-Free  Languages,  Mathematical  Systems
  2068.      Theory 2, 2 (June 1968), 127-146.
  2069.  
  2070. [Knu71]
  2071.      D.  E.  Knuth,   Semantics   of   Context-free   Languages:   Correction,
  2072.      Mathematical Systems Theory 5, (Mar. 1971), 95-96.
  2073.  
  2074. [Lam87]
  2075.      D. A. Lamb, IDL: Sharing Intermediate Representations, ACM  Trans.  Prog.
  2076.      Lang. and Systems 9, 3 (July 1987), 297-318.
  2077.  
  2078. [Mar90]
  2079.      M. Martin, Entwurf und Implementierung  eines  Ubersetzers  von  Modula-2
  2080.      nach  C, Diplomarbeit, GMD Forschungsstelle an der Universitat Karlsruhe,
  2081.      Feb. 1990.
  2082.  
  2083. [NNG89]
  2084.      J. R. Nestor, J. M. Newcomer, P. Giannini  and  D.  L.  Stone,  IDL:  The
  2085.      Language and its Implementation, Prentice Hall, Englewood Cliffs, 1989.
  2086.  
  2087. [Par88]
  2088.      J. C. H. Park, y+: A Yacc  Preprocessor  for  Certain  Semantic  Actions,
  2089.      SIGPLAN Notices 23, 6 (1988), 97-106.
  2090.  
  2091. [WGS89]
  2092.      W. M. Waite, J. Grosch and F. W. Schroer, Three Compiler  Specifications,
  2093.      GMD-Studie  Nr.  166,  GMD Forschungsstelle an der Universitat Karlsruhe,
  2094.      Aug. 1989.
  2095.  
  2096. [Wir88a]
  2097.      N. Wirth, The Programming Language Oberon, Software-Practice & Experience
  2098.      18, 7 (July 1988), 671-690.
  2099.  
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.                                      Ast                                    31
  2110.  
  2111.  
  2112. [Wir88b]
  2113.      N. Wirth, From Modula to Oberon, Software-Practice  &  Experience  18,  7
  2114.      (July 1988), 661-670.
  2115.  
  2116. [Wir88c]
  2117.      N. Wirth, Type Extensions, ACM Trans. Prog. Lang. and Systems 10, 2 (Apr.
  2118.      1988), 204-214.
  2119.  
  2120.  
  2121.  
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.  
  2171.  
  2172.  
  2173.  
  2174.                                      Ast                                    32
  2175.  
  2176.  
  2177. Appendix 1: Syntax of the Specification Language
  2178.  
  2179. RULE                                    /* Ast: concrete syntax */
  2180.  
  2181. /* parser grammar */
  2182.  
  2183. Specification    = <
  2184.                  =               TreeCodes PropPart DeclPart RulePart Modules .
  2185.                  = 'MODULE' Name TreeCodes PropPart DeclPart RulePart
  2186.                    'END' Name Modules .
  2187. > .
  2188. TreeCodes        = <
  2189.                  =             SubUnit .
  2190.                  = 'TREE'      SubUnit Codes .
  2191.                  = 'TREE' Name SubUnit Codes .
  2192. > .
  2193. Codes            = <
  2194.                  = .
  2195.                  = Codes 'EXPORT' tTargetCode .
  2196.                  = Codes 'IMPORT' tTargetCode .
  2197.                  = Codes 'GLOBAL' tTargetCode .
  2198.                  = Codes 'LOCAL'  tTargetCode .
  2199.                  = Codes 'BEGIN'  tTargetCode .
  2200.                  = Codes 'CLOSE'  tTargetCode .
  2201. > .
  2202. SubUnit          = <
  2203.                  = .
  2204.                  = SubUnit 'SUBUNIT' Name .
  2205.                  = SubUnit 'VIEW'    Name .
  2206. > .
  2207. PropPart         = Props .
  2208.  
  2209. Props            = <
  2210.                  =
  2211.                  = Props 'PROPERTY' Properties
  2212.                  = Props 'PROPERTY' Properties 'FOR' Names
  2213.                  = Props 'SELECT' Names
  2214. > .
  2215. DeclPart         = <
  2216.                  = .
  2217.                  = 'DECLARE' Decls .
  2218. > .
  2219. Decls            = <
  2220.                  = .
  2221.    MoreNonterms  = Decls Names '=' AttrDecls '.' .
  2222.    MoreTerminals = Decls Names ':' AttrDecls '.' .
  2223. > .
  2224. Names            = <
  2225.                  = .
  2226.                  = Names Name .
  2227.                  = Names ',' .
  2228. > .
  2229. RulePart         = <
  2230.  
  2231.  
  2232.  
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.                                      Ast                                    33
  2241.  
  2242.  
  2243.                  = .
  2244.                  = 'RULE' Types .
  2245. > .
  2246. Types            = <
  2247.                  = .
  2248.    Nonterminal   = Types Name BaseTypes '='  AttrDecls Extensions '.' .
  2249.    Terminal      = Types Name BaseTypes ':'  AttrDecls Extensions '.' .
  2250.    Abstract      = Types Name BaseTypes ':=' AttrDecls Extensions '.' .
  2251. > .
  2252. BaseTypes        = <
  2253.                  = .
  2254.                  = '<-' Names .
  2255. > .
  2256. Extensions       = <
  2257.                  = .
  2258.                  = '<' Types '>' .
  2259. > .
  2260. AttrDecls        = <
  2261.                  = .
  2262.    ChildSelct    = AttrDecls     Name ':' Name Properties .
  2263.    ChildNoSelct  = AttrDecls              Name Properties .
  2264.    AttrTyped     = AttrDecls '[' Name ':' Name Properties ']' .
  2265.    AttrInteger   = AttrDecls '[' Name          Properties ']' .
  2266. > .
  2267. Properties       = <
  2268.                  = .
  2269.                  = Properties 'INPUT' .
  2270.                  = Properties 'OUTPUT' .
  2271.                  = Properties 'SYNTHESIZED' .
  2272.                  = Properties 'INHERITED' .
  2273.                  = Properties 'THREAD' .
  2274.                  = Properties 'REVERSE' .
  2275.                  = Properties 'IGNORE' .
  2276.                  = Properties 'VIRTUAL' .
  2277. > .
  2278. Modules          = <
  2279.                  = .
  2280.                  = Modules 'MODULE' Name TreeCodes DeclPart RulePart 'END' Name .
  2281. > .
  2282. Name             = <
  2283.                  = tIdent .
  2284.                  = tString .
  2285. > .
  2286.  
  2287. /* lexical grammar */
  2288.  
  2289. tIdent           : <
  2290.                  = Letter .
  2291.                  = tIdent Letter .
  2292.                  = tIdent Digit .
  2293.                  = tIdent '_' .
  2294. > .
  2295. tString          : <
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.                                      Ast                                    34
  2307.  
  2308.  
  2309.                  = "'" Characters "'" .
  2310.                  = '"' Characters '"' .
  2311. > .
  2312. tTargetCode      : '{' Characters '}' .
  2313.  
  2314. Comment          : '/*' Characters '*/' .
  2315.  
  2316. Characters       : <
  2317.                  = .
  2318.                  = Characters Character .
  2319. > .
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.  
  2342.  
  2343.  
  2344.  
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350.  
  2351.  
  2352.  
  2353.  
  2354.  
  2355.  
  2356.  
  2357.  
  2358.  
  2359.  
  2360.  
  2361.  
  2362.  
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.                                      Ast                                    35
  2372.  
  2373.  
  2374. Appendix 2: Concrete Syntax of the Example Language MiniLAX
  2375.  
  2376. RULE
  2377. Prog            = PROGRAM tIdent ';' 'DECLARE' Decls 'BEGIN' Stats 'END' '.' .
  2378. Decls           = <
  2379.    Decls1       = Decl .
  2380.    Decls2       = Decls ';' Decl .
  2381. > .
  2382. Decl            = <
  2383.    Var          = tIdent ':' Type .
  2384.    Proc0        = PROCEDURE tIdent ';' 'DECLARE' Decls 'BEGIN' Stats 'END' .
  2385.    Proc         = PROCEDURE tIdent '(' Formals ')' ';'
  2386.                                        'DECLARE' Decls 'BEGIN' Stats 'END' .
  2387. > .
  2388. Formals         = <
  2389.    Formals1     = Formal .
  2390.    Formals2     = Formals ';' Formal .
  2391. > .
  2392. Formal          = <
  2393.    Value        = tIdent ':' Type .
  2394.    Ref          = VAR tIdent ':' Type .
  2395. > .
  2396. Type            = <
  2397.    Int          = INTEGER .
  2398.    Real         = REAL .
  2399.    Bool         = BOOLEAN .
  2400.    Array        = ARRAY '[' Lwb: tIntegerConst '..' Upb: tIntegerConst ']' OF Type .
  2401. > .
  2402. Stats           = <
  2403.    Stats1       = Stat .
  2404.    Stats2       = Stats ';' Stat .
  2405. > .
  2406. Stat            = <
  2407.    Assign       = Adr ':=' Expr .
  2408.    Call0        = tIdent .
  2409.    Call         = tIdent '(' Actuals ')' .
  2410.    If           = IF Expr THEN Then: Stats ELSE Else: Stats 'END' .
  2411.    While        = WHILE Expr DO Stats 'END' .
  2412.    Read         = READ '(' Adr ')' .
  2413.    Write        = WRITE '(' Expr ')' .
  2414. > .
  2415. Actuals         = <
  2416.    Expr1        = Expr .
  2417.    Expr2        = Actuals ',' Expr .
  2418. > .
  2419. Expr            = <
  2420.    Less         = Lop: Expr '<' Rop: Expr .
  2421.    Plus         = Lop: Expr '+' Rop: Expr .
  2422.    Times        = Lop: Expr '*' Rop: Expr .
  2423.    Not          = NOT Expr .
  2424.    '()'         = '(' Expr ')' .
  2425.    IConst       = tIntegerConst .
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.                                      Ast                                    36
  2437.  
  2438.  
  2439.    RConst       = tRealConst .
  2440.    False        = FALSE .
  2441.    True         = TRUE .
  2442.    Adr          = <
  2443.       Name      = tIdent .
  2444.       Index     = Adr '[' Expr ']' .
  2445.    > .
  2446. > .
  2447. tIdent          : [Ident: tIdent] .
  2448. tIntegerConst   : [Integer      ] .
  2449. tRealConst      : [Real : REAL  ] .
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465.  
  2466.  
  2467.  
  2468.  
  2469.  
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.  
  2480.  
  2481.  
  2482.  
  2483.  
  2484.  
  2485.  
  2486.  
  2487.  
  2488.  
  2489.  
  2490.  
  2491.  
  2492.  
  2493.  
  2494.  
  2495.  
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.                                      Ast                                    37
  2502.  
  2503.  
  2504. Appendix 3: Abstract Syntax of the Example Language MiniLAX
  2505.  
  2506. TREE                                    /* MiniLAX: abstract syntax */
  2507. IMPORT  { FROM Idents IMPORT tIdent;
  2508.           TYPE tPosition = RECORD Line, Column: CARDINAL; END; }
  2509.  
  2510. GLOBAL  { FROM Idents IMPORT tIdent; }
  2511.  
  2512. RULE
  2513.  
  2514. MiniLax         = Proc .
  2515. Decls           = <
  2516.    NoDecl       = .
  2517.    Decl         = Next: Decls REV [Ident: tIdent] [Pos: tPosition] <
  2518.       Proc      = Formals Decls Stats .
  2519.       Var       = Type .
  2520.    > .
  2521. > .
  2522. Formals         = <
  2523.    NoFormal     = .
  2524.    Formal       = Next: Formals REV [Ident: tIdent] [Pos: tPosition] Type .
  2525. > .
  2526. Type            = <
  2527.    Integer      = .
  2528.    Real         = .
  2529.    Boolean      = .
  2530.    Array        = Type                [Lwb] [Upb] [Pos: tPosition] .
  2531.    Ref          = Type .
  2532. > .
  2533. Stats           = <
  2534.    NoStat       = .
  2535.    Stat         = Next: Stats REV <
  2536.       Assign    = Adr Expr            [Pos: tPosition] .
  2537.       Call      = Actuals             [Ident: tIdent] [Pos: tPosition] .
  2538.       If        = Expr Then: Stats Else: Stats .
  2539.       While     = Expr Stats .
  2540.       Read      = Adr .
  2541.       Write     = Expr .
  2542.    > .
  2543. > .
  2544. Actuals         = <
  2545.    NoActual     =                     [Pos: tPosition] .
  2546.    Actual       = Next: Actuals REV Expr .
  2547. > .
  2548. Expr            =                     [Pos: tPosition] <
  2549.    Binary       = Lop: Expr Rop: Expr [Operator] .
  2550.    Unary        = Expr                [Operator] .
  2551.    IntConst     =                     [Value         ] .
  2552.    RealConst    =                     [Value: REAL   ] .
  2553.    BoolConst    =                     [Value: BOOLEAN] .
  2554.    Adr          = <
  2555.       Index     = Adr Expr .
  2556.       Ident     =                     [Ident: tIdent] .
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.                                      Ast                                    38
  2568.  
  2569.  
  2570.    > .
  2571. > .
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.  
  2582.  
  2583.  
  2584.  
  2585.  
  2586.  
  2587.  
  2588.  
  2589.  
  2590.  
  2591.  
  2592.  
  2593.  
  2594.  
  2595.  
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.  
  2608.  
  2609.  
  2610.  
  2611.  
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.                                      Ast                                    39
  2633.  
  2634.  
  2635. Appendix 4: Generated Header File for C
  2636. # ifndef yyTREE   /* throughout replace TREE by the name of the tree module */
  2637. # define yyTREE
  2638. <import_declarations>
  2639. # define bool char
  2640. # define NoTREE (tTREE) NULL
  2641. # define k<type_1> 1
  2642. # define k<type_1> 2
  2643.    ...
  2644. typedef unsigned short TREE_tKind;   /* or char */
  2645. typedef unsigned short TREE_tMark;
  2646. typedef unsigned short TREE_tLabel;
  2647. typedef union TREE_Node * tTREE;
  2648. typedef void (* TREE_tProcTree) ();
  2649. <export_declarations>
  2650. # ifndef TREE_NodeHead
  2651. # define TREE_NodeHead
  2652. # endif
  2653. typedef struct { TREE_tKind yyKind; TREE_tMark yyMark; TREE_NodeHead } TREE_tNodeHead;
  2654. typedef struct { TREE_tNodeHead yyHead;
  2655.                  <children_and_attributes_of_type_1> } y<type_1>;
  2656. typedef struct { TREE_tNodeHead yyHead;
  2657.                  <children_and_attributes_of_type_2> } y<type_2>;
  2658.    ...
  2659. union TREE_Node {
  2660.    TREE_tKind Kind;
  2661.    TREE_tNodeHead yyHead;
  2662.    y<type_1> <type_1>;
  2663.    y<type_2> <type_2>;
  2664.     ...
  2665. };
  2666. extern tTREE TREERoot;
  2667. extern unsigned long TREE_HeapUsed;
  2668. extern unsigned short TREE_NodeSize [];
  2669. extern char * TREE_NodeName [];
  2670. extern tTREE n<type_1>          ();
  2671. extern tTREE n<type_2>          ();
  2672.    ...
  2673. extern tTREE m<type_1>          (<input_children_and_attributes_of_type_1>);
  2674. extern tTREE m<type_2>          (<input_children_and_attributes_of_type_2>);
  2675.    ...
  2676. extern tTREE MakeTREE           (TREE_tKind Kind);
  2677. extern bool  TREE_IsType        (tTREE t, TREE_tKind Kind);
  2678. extern void  ReleaseTREE        (tTREE t);
  2679. extern void  ReleaseTREEModule  ();
  2680. extern void  WriteTREENode      (FILE * f, tTREE t);
  2681. extern void  WriteTREE          (FILE * f, tTREE t);
  2682. extern tTREE ReadTREE           (FILE * f);
  2683. extern void  PutTREE            (FILE * f, tTREE t);
  2684. extern tTREE GetTREE            (FILE * f);
  2685. extern void  TraverseTREETD     (tTREE t, void (* Procedure) (tTREE t));
  2686. extern void  TraverseTREEBU     (tTREE t, void (* Procedure) (tTREE t));
  2687. extern tTREE ReverseTREE        (tTREE t);
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698.                                      Ast                                    40
  2699.  
  2700.  
  2701. extern tTREE CopyTREE           (tTREE t);
  2702. extern bool  CheckTREE          (tTREE t);
  2703. extern void  QueryTREE          (tTREE t);
  2704. extern bool  IsEqualTREE        (tTREE t1, tTREE t2);
  2705. extern void  BeginTREE          ();
  2706. extern void  CloseTREE          ();
  2707. # endif
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.                                      Ast                                    41
  2764.  
  2765.  
  2766. Appendix 5: Generated Definition Module for Modula-2
  2767. DEFINITION MODULE TREE;
  2768.    IMPORT IO;     (* throughout replace TREE by the name of the tree module *)
  2769.    <import_declarations>
  2770.    CONST
  2771.       NoTREE       = NIL;
  2772.       <type_1>     = 1;
  2773.       <type_2>     = 2;
  2774.       ...
  2775.    TYPE
  2776.       tTREE        = POINTER TO yyNode;
  2777.       tProcTree    = PROCEDURE (tTREE);
  2778.    <export_declarations>
  2779.    TYPE
  2780.       yytNodeHead  = RECORD yyKind, yyMark: SHORTCARD; END;
  2781.    TYPE
  2782.       y<type_1>    = RECORD yyHead: yytNodeHead;
  2783.                             <children_and_attributes_of_type_1> END;
  2784.       y<type_2>    = RECORD yyHead: yytNodeHead;
  2785.                             <children_and_attributes_of_type_2> END;
  2786.       ...
  2787.       yyNode       = RECORD
  2788.          CASE : SHORTCARD OF
  2789.          | 0        : Kind: SHORTCARD;
  2790.          | ...      : yyHead: yytNodeHead;
  2791.          | <type_1> : <type_1>    : y<type_1>;
  2792.          | <type_2> : <type_2>    : y<type_2>;
  2793.          ...
  2794.          END;
  2795.       END;
  2796.    VAR TREERoot  : tTREE;
  2797.    VAR HeapUsed  : LONGCARD;
  2798.    VAR yyNodeSize: ARRAY [ ... ] OF SHORTCARD;
  2799.    PROCEDURE n<type_1>      (): tTREE;
  2800.    PROCEDURE n<type_2>      (): tTREE;
  2801.    ...
  2802.    PROCEDURE m<type_1>      (<input_children_and_attributes_of_type_1>): tTREE;
  2803.    PROCEDURE m<type_2>      (<input_children_and_attributes_of_type_2>): tTREE;
  2804.    ...
  2805.    PROCEDURE MakeTREE       (Kind: SHORTCARD): tTREE;
  2806.    PROCEDURE IsType         (Tree: tTREE; Kind: SHORTCARD): BOOLEAN;
  2807.    PROCEDURE ReleaseTREE    (Tree: tTREE);
  2808.    PROCEDURE ReleaseTREEModule;
  2809.    PROCEDURE WriteTREENode  (f: IO.tFile; Tree: tTREE);
  2810.    PROCEDURE WriteTREE      (f: IO.tFile; Tree: tTREE);
  2811.    PROCEDURE ReadTREE       (f: IO.tFile): tTREE;
  2812.    PROCEDURE PutTREE        (f: IO.tFile; Tree: tTREE);
  2813.    PROCEDURE GetTREE        (f: IO.tFile): tTREE;
  2814.    PROCEDURE ReverseTREE    (Tree: tTREE): tTREE;
  2815.    PROCEDURE TraverseTREETD (Tree: tTREE; Proc: tProcTree);
  2816.    PROCEDURE TraverseTREEBU (Tree: tTREE; Proc: tProcTree);
  2817.    PROCEDURE CopyTREE       (Tree: tTREE): tTree;
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.                                      Ast                                    42
  2829.  
  2830.  
  2831.    PROCEDURE CheckTREE      (Tree: tTREE): BOOLEAN;
  2832.    PROCEDURE QueryTREE      (Tree: tTREE);
  2833.    PROCEDURE IsEqualTREE    (Tree1, Tree2: tTREE): BOOLEAN;
  2834.    PROCEDURE BeginTREE;
  2835.    PROCEDURE CloseTREE;
  2836. END TREE.
  2837.  
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844.  
  2845.  
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853.  
  2854.  
  2855.  
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876.  
  2877.  
  2878.  
  2879.  
  2880.  
  2881.  
  2882.  
  2883.  
  2884.  
  2885.  
  2886.  
  2887.  
  2888.  
  2889.  
  2890.  
  2891.  
  2892.  
  2893.                                      Ast                                    43
  2894.  
  2895.  
  2896. Appendix 6: Predefined Type Operations for C
  2897.  
  2898. /* int */
  2899. # define beginint(a)
  2900. # define closeint(a)
  2901. # define readint(a)             (void) fscanf (yyf, "%d", & a);
  2902. # define writeint(a)            (void) fprintf (yyf, "%d", a);
  2903. # define getint(a)              yyGet ((char *) & a, sizeof (a));
  2904. # define putint(a)              yyPut ((char *) & a, sizeof (a));
  2905. # define copyint(a, b)
  2906. # define equalint(a, b)         a == b
  2907. /* short */
  2908. # define beginshort(a)
  2909. # define closeshort(a)
  2910. # define readshort(a)           (void) fscanf (yyf, "%hd", & a);
  2911. # define writeshort(a)          (void) fprintf (yyf, "%hd", a);
  2912. # define getshort(a)            yyGet ((char *) & a, sizeof (a));
  2913. # define putshort(a)            yyPut ((char *) & a, sizeof (a));
  2914. # define copyshort(a, b)
  2915. # define equalshort(a, b)       a == b
  2916. /* long */
  2917. # define beginlong(a)
  2918. # define closelong(a)
  2919. # define readlong(a)            (void) fscanf (yyf, "%ld", & a);
  2920. # define writelong(a)           (void) fprintf (yyf, "%ld", a);
  2921. # define getlong(a)             yyGet ((char *) & a, sizeof (a));
  2922. # define putlong(a)             yyPut ((char *) & a, sizeof (a));
  2923. # define copylong(a, b)
  2924. # define equallong(a, b)        a == b
  2925. /* unsigned */
  2926. # define beginunsigned(a)
  2927. # define closeunsigned(a)
  2928. # define readunsigned(a)        (void) fscanf (yyf, "%u", & a);
  2929. # define writeunsigned(a)       (void) fprintf (yyf, "%u", a);
  2930. # define getunsigned(a)         yyGet ((char *) & a, sizeof (a));
  2931. # define putunsigned(a)         yyPut ((char *) & a, sizeof (a));
  2932. # define copyunsigned(a, b)
  2933. # define equalunsigned(a, b)    a == b
  2934. /* float */
  2935. # define beginfloat(a)
  2936. # define closefloat(a)
  2937. # define readfloat(a)           (void) fscanf (yyf, "%g", & a);
  2938. # define writefloat(a)          (void) fprintf (yyf, "%g", a);
  2939. # define getfloat(a)            yyGet ((char *) & a, sizeof (a));
  2940. # define putfloat(a)            yyPut ((char *) & a, sizeof (a));
  2941. # define copyfloat(a, b)
  2942. # define equalfloat(a, b)       a == b
  2943. /* double */
  2944. # define begindouble(a)
  2945. # define closedouble(a)
  2946. # define readdouble(a)          (void) fscanf (yyf, "%lg", & a);
  2947. # define writedouble(a)         (void) fprintf (yyf, "%lg", a);
  2948. # define getdouble(a)           yyGet ((char *) & a, sizeof (a));
  2949.  
  2950.  
  2951.  
  2952.  
  2953.  
  2954.  
  2955.  
  2956.  
  2957.  
  2958.  
  2959.                                      Ast                                    44
  2960.  
  2961.  
  2962. # define putdouble(a)           yyPut ((char *) & a, sizeof (a));
  2963. # define copydouble(a, b)
  2964. # define equaldouble(a, b)      a == b
  2965. /* bool */
  2966. # define beginbool(a)
  2967. # define closebool(a)
  2968. # define readbool(a)            a = fgetc (yyf) == 'T';
  2969. # define writebool(a)           (void) fputc (a ? 'T' : 'F', yyf);
  2970. # define getbool(a)             yyGet ((char *) & a, sizeof (a));
  2971. # define putbool(a)             yyPut ((char *) & a, sizeof (a));
  2972. # define copybool(a, b)
  2973. # define equalbool(a, b)        a == b
  2974. /* char */
  2975. # define beginchar(a)
  2976. # define closechar(a)
  2977. # define readchar(a)            a = fgetc (yyf);
  2978. # define writechar(a)           (void) fputc (a, yyf);
  2979. # define getchar(a)             yyGet ((char *) & a, sizeof (a));
  2980. # define putchar(a)             yyPut ((char *) & a, sizeof (a));
  2981. # define copychar(a, b)
  2982. # define equalchar(a, b)        a == b
  2983. /* tString */
  2984. # define begintString(a)
  2985. # define closetString(a)
  2986. # define readtString(a)
  2987. # define writetString(a)        (void) fputs (a, yyf);
  2988. # define gettString(a)
  2989. # define puttString(a)
  2990. # define copytString(a, b)
  2991. # define equaltString(a, b)     strcmp (a, b)
  2992. /* tStringRef */
  2993. # define begintStringRef(a)
  2994. # define closetStringRef(a)
  2995. # define readtStringRef(a)
  2996. # define writetStringRef(a)     WriteString (yyf, a);
  2997. # define gettStringRef(a)
  2998. # define puttStringRef(a)
  2999. # define copytStringRef(a, b)
  3000. # define equaltStringRef(a, b)  a == b
  3001. /* tIdent */
  3002. # define begintIdent(a)
  3003. # define closetIdent(a)
  3004. # define readtIdent(a)          a = yyReadIdent ();
  3005. # define writetIdent(a)         WriteIdent (yyf, a);
  3006. # define gettIdent(a)           yyGetIdent (& a);
  3007. # define puttIdent(a)           yyPutIdent (a);
  3008. # define copytIdent(a, b)
  3009. # define equaltIdent(a, b)      a == b
  3010. /* tSet */
  3011. # define begintSet(a)
  3012. # define closetSet(a)
  3013. # define readtSet(a)            ReadSet (yyf, & a);
  3014. # define writetSet(a)           WriteSet (yyf, & a);
  3015.  
  3016.  
  3017.  
  3018.  
  3019.  
  3020.  
  3021.  
  3022.  
  3023.  
  3024.  
  3025.                                      Ast                                    45
  3026.  
  3027.  
  3028. # define gettSet(a)
  3029. # define puttSet(a)
  3030. # define copytSet(a, b)
  3031. # define equaltSet(a, b)        IsEqual (& a, & b)
  3032. /* tPosition */
  3033. # define begintPosition(a)
  3034. # define closetPosition(a)
  3035. # define readtPosition(a)
  3036. # define writetPosition(a)      WritePosition (yyf, a);
  3037. # define gettPosition(a)
  3038. # define puttPosition(a)
  3039. # define copytPosition(a, b)
  3040. # define equaltPosition(a, b)   Compare (a, b) == 0
  3041.  
  3042.  
  3043.  
  3044.  
  3045.  
  3046.  
  3047.  
  3048.  
  3049.  
  3050.  
  3051.  
  3052.  
  3053.  
  3054.  
  3055.  
  3056.  
  3057.  
  3058.  
  3059.  
  3060.  
  3061.  
  3062.  
  3063.  
  3064.  
  3065.  
  3066.  
  3067.  
  3068.  
  3069.  
  3070.  
  3071.  
  3072.  
  3073.  
  3074.  
  3075.  
  3076.  
  3077.  
  3078.  
  3079.  
  3080.  
  3081.  
  3082.  
  3083.  
  3084.  
  3085.  
  3086.  
  3087.  
  3088.  
  3089.  
  3090.                                      Ast                                    46
  3091.  
  3092.  
  3093. Appendix 7: Predefined Type Operations for Modula-2
  3094. (* INTEGER *)
  3095. # define beginINTEGER(a)
  3096. # define closeINTEGER(a)
  3097. # define readINTEGER(a)         a := IO.ReadI (yyf);
  3098. # define writeINTEGER(a)        IO.WriteI (yyf, a, 0);
  3099. # define getINTEGER(a)          yyGet (a);
  3100. # define putINTEGER(a)          yyPut (a);
  3101. # define copyINTEGER(a, b)
  3102. # define equalINTEGER(a, b)     a = b
  3103. (* SHORTINT *)
  3104. # define beginSHORTINT(a)
  3105. # define closeSHORTINT(a)
  3106. # define readSHORTINT(a)        a := IO.ReadI (yyf);
  3107. # define writeSHORTINT(a)       IO.WriteI (yyf, a, 0);
  3108. # define getSHORTINT(a)         yyGet (a);
  3109. # define putSHORTINT(a)         yyPut (a);
  3110. # define copySHORTINT(a, b)
  3111. # define equalSHORTINT(a, b)    a = b
  3112. (* LONGINT *)
  3113. # define beginLONGINT(a)
  3114. # define closeLONGINT(a)
  3115. # define readLONGINT(a)         a := IO.ReadI (yyf);
  3116. # define writeLONGINT(a)        IO.WriteI (yyf, a, 0);
  3117. # define getLONGINT(a)          yyGet (a);
  3118. # define putLONGINT(a)          yyPut (a);
  3119. # define copyLONGINT(a, b)
  3120. # define equalLONGINT(a, b)     a = b
  3121. (* CARDINAL *)
  3122. # define beginCARDINAL(a)
  3123. # define closeCARDINAL(a)
  3124. # define readCARDINAL(a)        a := IO.ReadI (yyf);
  3125. # define writeCARDINAL(a)       IO.WriteI (yyf, a, 0);
  3126. # define getCARDINAL(a)         yyGet (a);
  3127. # define putCARDINAL(a)         yyPut (a);
  3128. # define copyCARDINAL(a, b)
  3129. # define equalCARDINAL(a, b)    a = b
  3130. (* SHORTCARD *)
  3131. # define beginSHORTCARD(a)
  3132. # define closeSHORTCARD(a)
  3133. # define readSHORTCARD(a)       a := IO.ReadI (yyf);
  3134. # define writeSHORTCARD(a)      IO.WriteI (yyf, a, 0);
  3135. # define getSHORTCARD(a)        yyGet (a);
  3136. # define putSHORTCARD(a)        yyPut (a);
  3137. # define copySHORTCARD(a, b)
  3138. # define equalSHORTCARD(a, b)   a = b
  3139. (* LONGCARD *)
  3140. # define beginLONGCARD(a)
  3141. # define closeLONGCARD(a)
  3142. # define readLONGCARD(a)        a := IO.ReadI (yyf);
  3143. # define writeLONGCARD(a)       IO.WriteI (yyf, a, 0);
  3144. # define getLONGCARD(a)         yyGet (a);
  3145.  
  3146.  
  3147.  
  3148.  
  3149.  
  3150.  
  3151.  
  3152.  
  3153.  
  3154.  
  3155.                                      Ast                                    47
  3156.  
  3157.  
  3158. # define putLONGCARD(a)         yyPut (a);
  3159. # define copyLONGCARD(a, b)
  3160. # define equalLONGCARD(a, b)    a = b
  3161. (* REAL *)
  3162. # define beginREAL(a)
  3163. # define closeREAL(a)
  3164. # define readREAL(a)            a := IO.ReadR (yyf);
  3165. # define writeREAL(a)           IO.WriteR (yyf, a, 0, 6, 1);
  3166. # define getREAL(a)             yyGet (a);
  3167. # define putREAL(a)             yyPut (a);
  3168. # define copyREAL(a, b)
  3169. # define equalREAL(a, b)        a = b
  3170. (* LONGREAL *)
  3171. # define beginLONGREAL(a)
  3172. # define closeLONGREAL(a)
  3173. # define readLONGREAL(a)        a := IO.ReadR (yyf);
  3174. # define writeLONGREAL(a)       IO.WriteR (yyf, a, 0, 6, 1);
  3175. # define getLONGREAL(a)         yyGet (a);
  3176. # define putLONGREAL(a)         yyPut (a);
  3177. # define copyLONGREAL(a, b)
  3178. # define equalLONGREAL(a, b)    a = b
  3179. (* BOOLEAN *)
  3180. # define beginBOOLEAN(a)
  3181. # define closeBOOLEAN(a)
  3182. # define readBOOLEAN(a)         a := IO.ReadB (yyf);
  3183. # define writeBOOLEAN(a)        IO.WriteB (yyf, a);
  3184. # define getBOOLEAN(a)          yyGet (a);
  3185. # define putBOOLEAN(a)          yyPut (a);
  3186. # define copyBOOLEAN(a, b)
  3187. # define equalBOOLEAN(a, b)     a = b
  3188. (* CHAR *)
  3189. # define beginCHAR(a)
  3190. # define closeCHAR(a)
  3191. # define readCHAR(a)            a := IO.ReadC (yyf);
  3192. # define writeCHAR(a)           IO.WriteC (yyf, a);
  3193. # define getCHAR(a)             yyGet (a);
  3194. # define putCHAR(a)             yyPut (a);
  3195. # define copyCHAR(a, b)
  3196. # define equalCHAR(a, b)        a = b
  3197. (* BITSET *)
  3198. # define beginBITSET(a)
  3199. # define closeBITSET(a)
  3200. # define readBITSET(a)          yyReadHex (a);
  3201. # define writeBITSET(a)         yyWriteHex (a);
  3202. # define getBITSET(a)           yyGet (a);
  3203. # define putBITSET(a)           yyPut (a);
  3204. # define copyBITSET(a, b)
  3205. # define equalBITSET(a, b)      a = b
  3206. (* BYTE *)
  3207. # define beginBYTE(a)
  3208. # define closeBYTE(a)
  3209. # define readBYTE(a)            yyReadHex (a);
  3210. # define writeBYTE(a)           yyWriteHex (a);
  3211.  
  3212.  
  3213.  
  3214.  
  3215.  
  3216.  
  3217.  
  3218.  
  3219.  
  3220.  
  3221.                                      Ast                                    48
  3222.  
  3223.  
  3224. # define getBYTE(a)             yyGet (a);
  3225. # define putBYTE(a)             yyPut (a);
  3226. # define copyBYTE(a, b)
  3227. # define equalBYTE(a, b)        a = b
  3228. (* WORD *)
  3229. # define beginWORD(a)
  3230. # define closeWORD(a)
  3231. # define readWORD(a)            yyReadHex (a);
  3232. # define writeWORD(a)           yyWriteHex (a);
  3233. # define getWORD(a)             yyGet (a);
  3234. # define putWORD(a)             yyPut (a);
  3235. # define copyWORD(a, b)
  3236. # define equalWORD(a, b)        a = b
  3237. (* ADDRESS *)
  3238. # define beginADDRESS(a)
  3239. # define closeADDRESS(a)
  3240. # define readADDRESS(a)         yyReadHex (a);
  3241. # define writeADDRESS(a)        yyWriteHex (a);
  3242. # define getADDRESS(a)          yyGet (a);
  3243. # define putADDRESS(a)          yyPut (a);
  3244. # define copyADDRESS(a, b)
  3245. # define equalADDRESS(a, b)     a = b
  3246. (* tString *)
  3247. # define begintString(a)
  3248. # define closetString(a)
  3249. # define readtString(a)         Strings.ReadL (yyf, a);
  3250. # define writetString(a)        Strings.WriteL (yyf, a);
  3251. # define gettString(a)          yyGet (a);
  3252. # define puttString(a)          yyPut (a);
  3253. # define copytString(a, b)
  3254. # define equaltString(a, b)     Strings.IsEqual (a, b)
  3255. (* tStringRef *)
  3256. # define begintStringRef(a)
  3257. # define closetStringRef(a)
  3258. # define readtStringRef(a)
  3259. # define writetStringRef(a)     StringMem.WriteString (yyf, a);
  3260. # define gettStringRef(a)
  3261. # define puttStringRef(a)
  3262. # define copytStringRef(a, b)
  3263. # define equaltStringRef(a, b)  a = b
  3264. (* tIdent *)
  3265. # define begintIdent(a)
  3266. # define closetIdent(a)
  3267. # define readtIdent(a)          a := yyReadIdent ();
  3268. # define writetIdent(a)         Idents.WriteIdent (yyf, a);
  3269. # define gettIdent(a)           yyGetIdent (a);
  3270. # define puttIdent(a)           yyPutIdent (a);
  3271. # define copytIdent(a, b)
  3272. # define equaltIdent(a, b)      a = b
  3273. (* tText *)
  3274. # define begintText(a)
  3275. # define closetText(a)
  3276. # define readtText(a)
  3277.  
  3278.  
  3279.  
  3280.  
  3281.  
  3282.  
  3283.  
  3284.  
  3285.  
  3286.  
  3287.                                      Ast                                    49
  3288.  
  3289.  
  3290. # define writetText(a)          Texts.WriteText (yyf, a);
  3291. # define gettText(a)
  3292. # define puttText(a)
  3293. # define copytText(a, b)
  3294. # define equaltText(a, b)       FALSE
  3295. (* tSet *)
  3296. # define begintSet(a)
  3297. # define closetSet(a)
  3298. # define readtSet(a)            Sets.ReadSet (yyf, a);
  3299. # define writetSet(a)           Sets.WriteSet (yyf, a);
  3300. # define gettSet(a)
  3301. # define puttSet(a)
  3302. # define copytSet(a, b)
  3303. # define equaltSet(a, b)        Sets.IsEqual (a, b)
  3304. (* tRelation *)
  3305. # define begintRelation(a)
  3306. # define closetRelation(a)
  3307. # define readtRelation(a)       Relations.ReadRelation (yyf, a);
  3308. # define writetRelation(a)      Relations.WriteRelation (yyf, a);
  3309. # define gettRelation(a)
  3310. # define puttRelation(a)
  3311. # define copytRelation(a, b)
  3312. # define equaltRelation(a, b)   Relations.IsEqual (a, b)
  3313. (* tPosition *)
  3314. # define begintPosition(a)
  3315. # define closetPosition(a)
  3316. # define readtPosition(a)
  3317. # define writetPosition(a)      Positions.WritePosition (yyf, a);
  3318. # define gettPosition(a)
  3319. # define puttPosition(a)
  3320. # define copytPosition(a, b)
  3321. # define equaltPosition(a, b)   Positions.Compare (a, b) = 0
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329.  
  3330.  
  3331.  
  3332.  
  3333.  
  3334.  
  3335.  
  3336.  
  3337.  
  3338.  
  3339.  
  3340.  
  3341.  
  3342.  
  3343.  
  3344.  
  3345.  
  3346.  
  3347.  
  3348.  
  3349.  
  3350.  
  3351.  
  3352.                                      Ast                                     1
  3353.  
  3354.  
  3355. Contents
  3356. 1.      Introduction ....................................................    1
  3357. 2.      Specification ...................................................    1
  3358. 2.1.    Node Types ......................................................    1
  3359. 2.2.    Children ........................................................    2
  3360. 2.3.    Attributes ......................................................    3
  3361. 2.4.    Declare Clause ..................................................    3
  3362. 2.5.    Extensions ......................................................    3
  3363. 2.6.    Multiple Inheritance ............................................    4
  3364. 2.7.    Modules .........................................................    6
  3365. 2.8.    Properties ......................................................    6
  3366. 2.9.    Subunits ........................................................    9
  3367. 2.10.   Views ...........................................................    9
  3368. 2.11.   Reversal of Lists ...............................................   11
  3369. 2.11.1. LR Parsers ......................................................   11
  3370. 2.11.2. LL Parsers ......................................................   12
  3371. 2.12.   Target Code .....................................................   13
  3372. 2.13.   Common Node Fields ..............................................   14
  3373. 2.14.   Type Specific Operations ........................................   14
  3374. 2.15.   Storage Management ..............................................   17
  3375. 3.      About the Generated Program Module ..............................   17
  3376. 4.      Using the Generated Program Module ..............................   20
  3377. 5.      Related Research ................................................   22
  3378. 5.1.    Variant Records .................................................   22
  3379. 5.2.    Type Extensions .................................................   22
  3380. 5.3.    Context-Free Grammars ...........................................   23
  3381. 5.4.    Attribute Grammars ..............................................   23
  3382. 5.5.    Interface Description Language (IDL) ............................   24
  3383. 5.6.    Attribute Coupled Grammars ......................................   24
  3384. 5.7.    Object-Oriented Languages .......................................   24
  3385. 5.8.    Tree Grammars ...................................................   25
  3386. 6.      Hints on Specifying Abstract Syntax .............................   25
  3387. 7.      Examples ........................................................   26
  3388. 8.      Experiences .....................................................   26
  3389. 9.      Usage ...........................................................   27
  3390.         References ......................................................   29
  3391.         Appendix 1: Syntax of the Specification Language ................   32
  3392.         Appendix 2: Concrete Syntax of the Example Language MiniLAX .....   35
  3393.         Appendix 3: Abstract Syntax of the Example Language MiniLAX .....   37
  3394.         Appendix 4: Generated Header File for C .........................   39
  3395.         Appendix 5: Generated Definition Module for Modula-2 ............   41
  3396.         Appendix 6: Predefined Type Operations for C ....................   43
  3397.         Appendix 7: Predefined Type Operations for Modula-2 .............   46
  3398.  
  3399.  
  3400.  
  3401.  
  3402.  
  3403.  
  3404.  
  3405.  
  3406.  
  3407.  
  3408.  
  3409.  
  3410.  
  3411.  
  3412.  
  3413.